00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "DrawMolecule.h"
00026 #include "AtomColor.h"
00027 #include "AtomRep.h"
00028 #include "AtomSel.h"
00029 #include "utilities.h"
00030 #include "VMDApp.h"
00031 #include "MoleculeList.h"
00032 #include "CommandQueue.h"
00033 #include "CmdAnimate.h"
00034 #include "Stride.h"
00035 #include "PickList.h"
00036 #include "MaterialList.h"
00037 #include "Inform.h"
00038 #include "TextEvent.h"
00039 #include "DisplayDevice.h"
00040 #include "MoleculeGraphics.h"
00041 #include "BondSearch.h"
00042 #include "DrawForce.h"
00043 #include "VolumetricData.h"
00044
00046
00047 DrawMolecule::DrawMolecule(VMDApp *vmdapp, Displayable *par)
00048 : BaseMolecule(vmdapp->next_molid()),
00049 Displayable(par), app(vmdapp), repList(8) {
00050 repcounter = 0;
00051 curframe = -1;
00052 active = TRUE;
00053 did_secondary_structure = 0;
00054 molgraphics = new MoleculeGraphics(this);
00055 vmdapp->pickList->add_pickable(molgraphics);
00056 drawForce = new DrawForce(this);
00057
00058 invalidate_cov_scale();
00059 center[0] = center[1] = center[2] = 0.0f;
00060
00061 need_find_bonds = 0;
00062 }
00063
00064
00065
00066 DrawMolecule::~DrawMolecule() {
00067 int i;
00068
00069
00070 for(i=0; i < components(); i++) {
00071 app->pickList->remove_pickable(component(i));
00072 delete component(i);
00073 }
00074
00075 app->pickList->remove_pickable(molgraphics);
00076
00077
00078 for (i=timesteps.num()-1; i>=0; i--) {
00079 delete timesteps[i];
00080 timesteps.remove(i);
00081 }
00082
00083 delete molgraphics;
00084 }
00085
00087
00088
00089 DrawMolItem *DrawMolecule::component(int n) {
00090 if(n >= 0 && n < components())
00091 return repList[n];
00092 else
00093 return NULL;
00094 }
00095
00096
00097
00098 DrawMolItem *DrawMolecule::component_from_pickable(const Pickable *p) {
00099 for (int i=0; i<components(); i++)
00100 if (repList[i] == p) return repList[i];
00101 return NULL;
00102 }
00103
00104
00105
00106 int DrawMolecule::atom_displayed(int n) {
00107 if (displayed() && n >= 0 && n < nAtoms) {
00108 for (int i=(components() - 1); i >= 0; i--) {
00109 if ((repList[i])->atom_displayed(n))
00110 return TRUE;
00111 }
00112 }
00113 return FALSE;
00114 }
00115
00116
00117
00118 int DrawMolecule::del_rep(int n) {
00119 DrawMolItem *rep = component(n);
00120 if (rep) {
00121 app->pickList->remove_pickable(rep);
00122 delete rep;
00123 repList.remove(n);
00124 invalidate_cov_scale();
00125 }
00126
00127 return (rep != NULL);
00128 }
00129
00130
00131 void DrawMolecule::add_rep(AtomColor *ac, AtomRep *ar, AtomSel *as,
00132 const Material *am) {
00133
00134 char buf[50];
00135 sprintf(buf, "rep%d", repcounter++);
00136 DrawMolItem *rep = new DrawMolItem(buf, this, ac, ar, as);
00137 app->pickList->add_pickable(rep);
00138 rep->change_material(am);
00139 repList.append(rep);
00140 invalidate_cov_scale();
00141 }
00142
00143 int DrawMolecule::show_rep(int repid, int onoff) {
00144 DrawMolItem *rep = component(repid);
00145 if (rep) {
00146 if (onoff) rep->on();
00147 else rep->off();
00148 invalidate_cov_scale();
00149 return TRUE;
00150 }
00151 return FALSE;
00152 }
00153
00154
00155
00156 int DrawMolecule::change_rep(int n, AtomColor *ac, AtomRep *ar, const char *sel) {
00157 DrawMolItem *rep = component(n);
00158 if (rep) {
00159 rep->change_color(ac);
00160 rep->change_rep(ar);
00161 rep->change_sel(sel);
00162
00163 invalidate_cov_scale();
00164 return TRUE;
00165 }
00166
00167 return FALSE;
00168 }
00169
00170
00171
00172 void DrawMolecule::force_recalc(int reason) {
00173 int numcomp = components();
00174 for (int i=0; i<numcomp; i++) {
00175 component(i)->force_recalc(reason);
00176 }
00177
00178
00179
00180 need_matrix_recalc();
00181 app->commandQueue->runcommand(new CmdAnimNewFrame);
00182
00183
00184 if (reason & (DrawMolItem::MOL_REGEN | DrawMolItem::SEL_REGEN))
00185 invalidate_cov_scale();
00186 }
00187
00188
00189
00190 void DrawMolecule::change_pbc() {
00191 int numcomp = components();
00192 for (int i=0; i<numcomp; i++)
00193 component(i)->change_pbc();
00194
00195
00196
00197 notify();
00198 }
00199
00200
00201
00202 void DrawMolecule::change_ts() {
00203 int numcomp = components();
00204 for (int i=0; i<numcomp; i++)
00205 component(i)->change_ts();
00206
00207 molgraphics->prepare();
00208 drawForce->prepare();
00209
00210 notify();
00211
00212
00213 app->commandQueue->runcommand( new FrameEvent(id(), curframe) );
00214 }
00215
00216
00217
00218 int DrawMolecule::highlighted_rep() const {
00219 if (app->highlighted_molid != id())
00220 return -1;
00221 return app->highlighted_rep;
00222 }
00223
00224
00225
00226 int DrawMolecule::get_component_by_name(const char *nm) {
00227
00228 int numreps = repList.num();
00229 for (int i=0; i<numreps; i++) {
00230 if (!strcmp(repList[i]->name, nm))
00231 return i;
00232 }
00233 return -1;
00234 }
00235
00236
00237
00238 const char *DrawMolecule::get_component_name(int ind) {
00239 DrawMolItem *rep = component(ind);
00240 if (!rep)
00241 return FALSE;
00242 return rep->name;
00243 }
00244
00245 void DrawMolecule::prepare() {
00246 if (needUpdate()) {
00247 notify();
00248 }
00249 }
00250
00251 void DrawMolecule::override_current_frame(int n) {
00252 if (n == curframe) return;
00253 int num = timesteps.num();
00254 if ( num==0 ) return;
00255 if ( n<0 ) curframe = 0;
00256 else if ( n>=num ) curframe = num-1;
00257 else curframe = n;
00258 invalidate_cov_scale();
00259 }
00260
00261
00262 void DrawMolecule::notify() {
00263 int monnum = monitorlist.num();
00264 int nid = id();
00265 for (int i=0; i<monnum; i++)
00266 monitorlist[i]->notify(nid);
00267 }
00268
00269
00270
00271 void DrawMolecule::append_frame(Timestep *ts) {
00272 timesteps.append(ts);
00273
00274
00275
00276 override_current_frame(timesteps.num() - 1);
00277
00278
00279
00280
00281 change_ts();
00282
00283
00284 if (timesteps.num() == 1) {
00285 app->scene_resetview_newmoldata();
00286 }
00287
00288
00289 if (timesteps.num() >= 1) {
00290
00291 if (need_find_bonds == 1) {
00292 need_find_bonds = 0;
00293 vmd_bond_search(this, ts, -1, 0);
00294 } else if (need_find_bonds == 2) {
00295 need_find_bonds = 0;
00296 vmd_bond_search(this, ts, -1, 1);
00297 }
00298 }
00299
00300 addremove_ts();
00301 app->commandQueue->runcommand(new CmdAnimNewNumFrames);
00302 }
00303
00304
00305
00306 void DrawMolecule::duplicate_frame(const Timestep *ts) {
00307 Timestep *newts;
00308 if (ts == NULL) {
00309 newts = new Timestep(nAtoms);
00310 newts->zero_values();
00311 } else {
00312 newts = new Timestep(*ts);
00313 }
00314 append_frame(newts);
00315 }
00316
00317
00318
00319 void DrawMolecule::delete_frame(int n) {
00320 if (n<0 || n>=timesteps.num()) return;
00321 delete timesteps[n];
00322 timesteps.remove(n);
00323
00324
00325 addremove_ts();
00326 app->commandQueue->runcommand(new CmdAnimNewNumFrames);
00327
00328
00329 if (curframe >= timesteps.num()) {
00330 curframe = timesteps.num()-1;
00331 change_ts();
00332 }
00333 }
00334
00335
00336
00337 void DrawMolecule::addremove_ts() {
00338 int numcomp = components();
00339 for (int i=0; i<numcomp; i++)
00340 component(i)->change_traj();
00341 }
00342
00343
00344
00345 static float dnorm(const double *v) {
00346 return (float)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00347 }
00348
00349 void DrawMolecule::invalidate_cov_scale() {
00350 scalefactor = -1;
00351 }
00352
00353
00354 float DrawMolecule::scale_factor() {
00355 if (scalefactor < 0) update_cov_scale();
00356 if (scalefactor > 0) {
00357 return scalefactor;
00358
00359 } else if (molgraphics->num_elements() > 0) {
00360 return molgraphics->scale_factor();
00361
00362 } else if (volumeList.num() > 0) {
00363
00364
00365
00366
00367 const VolumetricData *data = volumeList[0];
00368 float x=dnorm(data->xaxis), y=dnorm(data->yaxis), z=dnorm(data->zaxis);
00369 float scale_factor = x > y ? x : y;
00370 scale_factor = scale_factor > z ? scale_factor : z;
00371 if (scale_factor > 0) return 1.5f/scale_factor;
00372 }
00373 return 1.0f;
00374 }
00375
00376
00377
00378 int DrawMolecule::cov(float& x, float& y, float& z) {
00379 if (scalefactor < 0) update_cov_scale();
00380
00381 if (scalefactor > 0) {
00382
00383 x = center[0]; y = center[1]; z = center[2];
00384
00385 } else if (molgraphics->num_elements() > 0) {
00386
00387 molgraphics->cov(x, y, z);
00388
00389 } else if (volumeList.num() > 0) {
00390
00391 const VolumetricData *data = volumeList[0];
00392 x = (float) (data->origin[0] +
00393 0.5*(data->xaxis[0] + data->yaxis[0] + data->zaxis[0]));
00394 y = (float) (data->origin[1] +
00395 0.5*(data->xaxis[1] + data->yaxis[1] + data->zaxis[1]));
00396 z = (float) (data->origin[2] +
00397 0.5*(data->xaxis[2] + data->yaxis[2] + data->zaxis[2]));
00398 } else {
00399 return FALSE;
00400 }
00401 return TRUE;
00402 }
00403
00404
00406 int DrawMolecule::recalc_bonds() {
00407 Timestep *ts = current();
00408
00409 if (ts) {
00410 clear_bonds();
00411 vmd_bond_search(this, ts, -1, 0);
00412 msgInfo << "Bond count: " << count_bonds() << sendmsg;
00413 return 0;
00414 }
00415
00416 msgInfo << "No coordinates" << sendmsg;
00417 return -1;
00418 }
00419
00420 int DrawMolecule::need_secondary_structure(int calc_if_not_yet_done) {
00421 if (did_secondary_structure) return TRUE;
00422
00423 if (calc_if_not_yet_done) {
00424 if (!current()) return FALSE;
00425 did_secondary_structure = TRUE;
00426 app->show_stride_message();
00427 if (ss_from_stride(this)) {
00428 msgErr << "Call to Stride program failed." << sendmsg;
00429 return FALSE;
00430 }
00431 return TRUE;
00432 }
00433
00434 did_secondary_structure = TRUE;
00435 return TRUE;
00436 }
00437
00438 void DrawMolecule::invalidate_ss() {
00439 did_secondary_structure = 0;
00440 }
00441
00442 int DrawMolecule::recalc_ss() {
00443 did_secondary_structure = 0;
00444 int success = need_secondary_structure(1);
00445 did_secondary_structure = 1;
00446
00447 if (success) for (int i=0; i<components(); i++) component(i)->change_ss();
00448 return success;
00449 }
00450
00451 void DrawMolecule::register_monitor(DrawMoleculeMonitor *mon) {
00452 monitorlist.append(mon);
00453 }
00454 void DrawMolecule::unregister_monitor(DrawMoleculeMonitor *mon) {
00455 monitorlist.remove(monitorlist.find(mon));
00456 }
00457
00458 void DrawMolecule::update_cov_scale() {
00459 const Timestep *ts = current();
00460 if (!ts) return;
00461 int i, n = ts->num;
00462
00463 if (!n) return;
00464
00465 float covx, covy, covz;
00466 float minposx, minposy, minposz;
00467 float maxposx, maxposy, maxposz;
00468
00469
00470 ResizeArray<int> tmp_(n);
00471 int *on = &tmp_[0];
00472 for (i=0; i<n; i++) on[i] = 0;
00473 for (int j=0; j<repList.num(); j++) {
00474 const DrawMolItem *rep = repList[j];
00475 if (!rep->displayed()) continue;
00476 const int *flgs = rep->atomSel->on;
00477 for (i=0; i<n; i++) on[i] |= flgs[i];
00478 }
00479
00480 int istart = -1;
00481 for (i=0; i<n; i++) {
00482 if (on[i]) {
00483 istart = i;
00484 break;
00485 }
00486 }
00487 if (istart < 0) {
00488
00489 istart = 0;
00490 for (i=0; i<n; i++) on[i] = 1;
00491 }
00492
00493
00494 const float *mpos = ts->pos + 3*istart;
00495 minposx = maxposx = mpos[0];
00496 minposy = maxposy = mpos[1];
00497 minposz = maxposz = mpos[2];
00498 covx = covy = covz = 0.0;
00499
00500 int icount = 0;
00501 for (i=istart; i<n; ++i, mpos += 3) {
00502 if (!on[i]) continue;
00503 ++icount;
00504
00505 const float xpos = mpos[0];
00506 const float ypos = mpos[1];
00507 const float zpos = mpos[2];
00508
00509 covx += xpos;
00510 covy += ypos;
00511 covz += zpos;
00512
00513 if (xpos < minposx) minposx = xpos;
00514 if (xpos > maxposx) maxposx = xpos;
00515
00516 if (ypos < minposy) minposy = ypos;
00517 if (ypos > maxposy) maxposy = ypos;
00518
00519 if (zpos < minposz) minposz = zpos;
00520 if (zpos > maxposz) maxposz = zpos;
00521 }
00522
00523
00524 center[0] = covx;
00525 center[1] = covy;
00526 center[2] = covz;
00527 vec_scale(center, 1.0f / icount, center);
00528
00529
00530 scalefactor = maxposx - minposx;
00531
00532
00533 if (scalefactor == 0.0) {
00534 scalefactor = 3.0;
00535 }
00536
00537 if ((maxposx - minposx) > scalefactor)
00538 scalefactor = maxposx - minposx;
00539 if ((maxposy - minposy) > scalefactor)
00540 scalefactor = maxposy - minposy;
00541 if ((maxposz - minposz) > scalefactor)
00542 scalefactor = maxposz - minposz;
00543
00544 scalefactor = 1.5f / scalefactor;
00545 }
00546