Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

DrawMolItem2.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: DrawMolItem2.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.34 $       $Date: 2011/06/08 18:26:09 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   A continuation of rendering types from DrawMolItem
00019  *
00020  ***************************************************************************/
00021 
00022 #include <stdlib.h>
00023 #include "DrawMolItem.h"
00024 #include "DrawMolecule.h"
00025 #include "Scene.h"
00026 
00027 // draw the backbone trace (along the C alphas)
00028 // if no proteins are found, connect consequtive C alpha
00029 
00031 // it is given the atom index
00032 // if it is invalid (<0) it puts a NULL on the queue
00033 // if it is valid, the new coords and index are pushed on the queue
00034 // If the 2nd and 3rd coords are valid, a line is drawn between them
00035 //   with the right colors, etc.
00036 #define PUSH_QUEUE(atomid) {                                            \
00037   if (atomid < 0) {                                                     \
00038     memmove(CA, CA+1, 3*sizeof(float *)); CA[3] = NULL;                 \
00039     memmove(indicies, indicies+1, 3*sizeof(int)); indicies[3] = -1;     \
00040   } else {                                                              \
00041     memmove(CA, CA+1, 3*sizeof(float *)); CA[3] = framepos+3*atomid;    \
00042     memmove(indicies, indicies+1, 3*sizeof(int)); indicies[3] = atomid; \
00043   }                                                                     \
00044   /* check if I need to draw a bond */                                  \
00045   if (CA[1] && CA[2] && atomSel->on[indicies[1]] && atomSel->on[indicies[2]]) { \
00046     float midcoord[3];                                                  \
00047     midcoord[0] = (CA[1][0] + CA[2][0])/2.0f;                           \
00048     midcoord[1] = (CA[1][1] + CA[2][1])/2.0f;                           \
00049     midcoord[2] = (CA[1][2] + CA[2][2])/2.0f;                           \
00050     cmdColorIndex.putdata(atomColor->color[indicies[1]], cmdList);      \
00051     make_connection(CA[0], CA[1], midcoord, NULL,                       \
00052                     brad, bres, use_cyl);                               \
00053     cmdColorIndex.putdata(atomColor->color[indicies[2]], cmdList);      \
00054     make_connection(NULL, midcoord, CA[2], CA[3],                       \
00055                   brad, bres, use_cyl);                                 \
00056   }                                                                     \
00057 }
00058 
00059 
00060 // clear out the queue by calling -1 (inserts NULLs)
00061 // This actual calls the queue three more times than need be for 
00062 // PUSH_QUEUE to work correctly, but I prefered to keep the semantics
00063 #define EMPTY_QUEUE {                           \
00064   int atomidcode = -1;                          \
00065   PUSH_QUEUE(atomidcode);                       \
00066   PUSH_QUEUE(atomidcode);                       \
00067   PUSH_QUEUE(atomidcode);                       \
00068   PUSH_QUEUE(atomidcode);                       \
00069 }
00070 
00071 
00072 void DrawMolItem::draw_trace(float *framepos, float brad, int bres, int linethickness) {
00073   int use_cyl = FALSE;
00074   if (bres <= 2 || brad < 0.01) { // then going to do lines
00075     append(DMATERIALOFF);
00076     cmdLineType.putdata(SOLIDLINE, cmdList);
00077     cmdLineWidth.putdata(linethickness, cmdList);
00078   } else {
00079     use_cyl = TRUE;
00080     append(DMATERIALON);
00081   }
00082 
00083   int pnum = mol->pfragList.num();
00084   if (pnum > 0) {
00085     // go along each protein fragment
00086     for (int pfrag=0; pfrag<pnum; pfrag++) {
00087 
00088       //   Reset the queue
00089       // I keep track of four C alphas since I want to use
00090       // the "make_connection" command to draw "extended"
00091       // cylinders at the CA bends, and need 4 coords to do that
00092       // find the CA coords for each residue
00093       float *CA[4] = {NULL, NULL, NULL, NULL};
00094       int indicies[4] = {-1, -1, -1, -1};
00095       int res_index;
00096 
00097       // go down the residues in each the protein fragment
00098       int rnum = mol->pfragList[pfrag]->num();
00099       for (int res=0; res<rnum; res++) {
00100         res_index = (*mol->pfragList[pfrag])[res];
00101         PUSH_QUEUE(mol->find_atom_in_residue("CA", res_index));
00102       }
00103       // flush out the queue
00104       EMPTY_QUEUE
00105     }
00106   } else {
00107     // if there are no proteins, check for sequential records with a CA
00108     // given the definition of a PDB file, I can go down the list
00109     // and see if record(i).name == CA and record(i-1).name == CA
00110     //        and record(i).resid = record(i-1).resid + 1
00111 
00112     // As before, to connect records nicely I want to track four at a time
00113     float *CA[4] = {NULL, NULL, NULL, NULL};
00114     int indicies[4] = {-1, -1, -1, -1};
00115     int num = mol->nAtoms;
00116     int ca_num = mol->atomNames.typecode("CA");
00117     int last_resid = -10000;
00118     int resid;
00119     for (int i=0; i<num; i++) {
00120       MolAtom *atm = mol->atom(i);
00121       if (atm->nameindex == ca_num) {
00122         // found a CA, is it sequential?
00123         resid = atm->resid;
00124         if (resid == last_resid + 1) {
00125           // Yippe! push it on the end of the queue
00126           PUSH_QUEUE(i);
00127         } else {
00128           EMPTY_QUEUE
00129           // and add this element
00130           PUSH_QUEUE(i);
00131         }
00132         last_resid = resid;
00133       } else {
00134         // didn't find a CA, so flush the queue
00135         EMPTY_QUEUE
00136         last_resid = -10000;
00137       }
00138     } // end of loop through atoms
00139     // and flush out any remaining data
00140     EMPTY_QUEUE
00141   } // end if check if has proteins
00142 
00143   // And do the same for nucleic acids
00144   int nnum = mol -> nfragList.num();
00145   if (nnum > 0) {
00146     // go along each nucleic fragment
00147     for (int nfrag=0; nfrag<nnum; nfrag++) {
00148       //   Reset the queue
00149       // I keep track of four P atoms since I want to use
00150       // the "make_connection" command to draw "extended"
00151       // cylinders at the P bends, and need 4 coords to do that
00152       // find the P coords for each residue
00153       // I keep the name CA since I want to use the same macros
00154       float *CA[4] = {NULL, NULL, NULL, NULL};
00155       int indicies[4] = {-1, -1, -1, -1};
00156       int res_index;
00157 
00158       // go down the residues in each the nucleic fragment
00159       int rnum = mol->nfragList[nfrag]->num();
00160       for (int res=0; res<rnum; res++) {
00161         res_index = (*mol->nfragList[nfrag])[res];
00162         PUSH_QUEUE(mol->find_atom_in_residue("P", res_index));
00163       }
00164       // flush out the queue
00165       EMPTY_QUEUE
00166     }
00167   } else {
00168     // if there are no proteins, check for sequential records with a P
00169     // given the definition of a PDB file, I can go down the list
00170     // and see if record(i).name == P and record(i-1).name == P
00171     //        and record(i).resid = record(i-1).resid + 1
00172 
00173     // As before, to connect records nicely I want to track four at a time
00174     float *CA[4] = {NULL, NULL, NULL, NULL};
00175     int indicies[4] = {-1, -1, -1, -1};
00176     int num = mol->nAtoms;
00177     int p_num = mol->atomNames.typecode("P");
00178     int last_resid = -10000;
00179     int resid;
00180     for (int i=0; i<num; i++) {
00181       MolAtom *atm = mol->atom(i);
00182       if (atm -> nameindex == p_num) {
00183         // found a P, is it sequential?
00184         resid = atm->resid;
00185         if (resid == last_resid + 1) {
00186           // Yippe! push it on the end of the queue
00187           PUSH_QUEUE(i);
00188         } else {
00189           EMPTY_QUEUE
00190           // and add this element
00191           PUSH_QUEUE(i);
00192         }
00193         last_resid = resid;
00194       } else {
00195         // didn't find a P, so flush the queue
00196         EMPTY_QUEUE
00197         last_resid = -10000;
00198       }
00199     } // end of loop through atoms
00200     // and flush out any remaining data
00201     EMPTY_QUEUE
00202 
00203   } // end if check if has nucleic acid residues
00204 }
00205 
00206 
00207 // Draw dot surface
00208 // the dot distribution is determined from Jon Leech's 'distribute'
00209 // code.  See ftp://ftp.cs.unc.edu/pub/users/leech/points.tar.gz
00210 // and ftp://netlib.att.com/netlib/att/math/sloane/electrons/
00211 // All the dots are precomputed
00212 #include "DrawMolItemSolventPoints.data"
00213 // Note:  DrawMolItem::num_dot_surfaces is actually defined in
00214 //    DrawMolItemSolventPoints.data
00215 void DrawMolItem::draw_dot_surface(float *framepos, float srad, int sres, int method) {
00216   // XXX Hack - the value used for num_dot_surfaces should be retrieved
00217   // from AtomRep, I'm just not sure how to do it at the moment. 
00218   int num_dot_surfaces = 13;   // See the Solvent section of AtomRepInfo 
00219 
00220   DispCmdLineArray cmdLineArray;
00221   float probe_radius = srad;
00222   // sphereres has range 1 to n
00223   int surface_resolution = sres - 1; 
00224   if (surface_resolution >= num_dot_surfaces)   // slight paranoia
00225     surface_resolution = num_dot_surfaces - 1;
00226   if (surface_resolution < 0) 
00227     surface_resolution = 0;
00228 
00229   int num_dots = dot_surface_num_points[surface_resolution];
00230   float *dots = dot_surface_points[surface_resolution];
00231   int num_edges = dot_surface_num_lines[surface_resolution];
00232   int *edges = dot_surface_lines[surface_resolution];
00233   int *flgs = new int[num_dots];
00234   const float *aradius = mol->radius();
00235 
00236   if (method < 0) method = 0; if (method > 2) method = 2;
00237 
00238   append(DMATERIALOFF); // disable shading in all cases 
00239   cmdLineType.putdata(SOLIDLINE, cmdList); // set line drawing parameters
00240   cmdLineWidth.putdata(1, cmdList);
00241 
00242   // XXX really needs to be done only when selection or color changed
00243   update_lookups(atomColor, atomSel, colorlookups); 
00244 
00245   // temp info for drawing the little plus sign
00246   // I looked - none of the points are along the x axis
00247   float xaxis[3] = {1.0, 0.0, 0.0};
00248   float perp1[3], perp2[3];
00249   float pos1[3], pos2[3];
00250 
00251   ResizeArray<float> verts;
00252   ResizeArray<float> colors;
00253 
00254   for (int icolor=0; icolor<MAXCOLORS; icolor++) {
00255     const ColorLookup &cl = colorlookups[icolor];
00256     if (cl.num == 0) continue;
00257 
00258     const float *rgb = scene->color_value(icolor);
00259     if (method != 0) {
00260       cmdColorIndex.putdata(icolor, cmdList);
00261     }
00262     // draw points which are not within range of the bonded atoms
00263     for (int j=0; j<cl.num; j++) {
00264       const int id = cl.idlist[j];
00265       const MolAtom *atom = mol->atom(id);
00266       const float *pos = framepos + 3*id;
00267       float radius = aradius[id] + probe_radius;
00268       for (int points=0; points < num_dots; points++) {
00269         const float *d = dots + 3*points;
00270         flgs[points] = 1;
00271         float xyz[3];
00272         vec_scale(xyz, radius, d);
00273         vec_add(xyz, xyz, pos);
00274         // check the neighbors
00275         for (int nbr=0; nbr < atom->bonds; nbr++) {
00276           int b = atom->bondTo[nbr];
00277           const MolAtom *atom2 = mol->atom(b);
00278           float r = aradius[b] + probe_radius;
00279           if (distance2(xyz, framepos + 3*b) < r*r) {
00280             flgs[points] = 0;
00281             break;
00282           }
00283           // check the neighbor's neighbors
00284           for (int nbr2=0; nbr2 < atom2->bonds; nbr2++) {
00285             int b2 = atom2->bondTo[nbr2];
00286             if (b2 == id) continue; // don't eliminate myself!
00287             float r2 = aradius[b2] + probe_radius;
00288             if (distance2(xyz, framepos + 3*b2) < r2*r2) {
00289               flgs[points] = 0;
00290               break;
00291             }
00292           }
00293           if (!flgs[points]) break;
00294         }
00295         if (!flgs[points]) continue;
00296 
00297         switch (method) {
00298         case 0:
00299           // draw it as a point
00300           colors.append(rgb[0]);
00301           colors.append(rgb[1]);
00302           colors.append(rgb[2]);
00303           verts.append(xyz[0]);
00304           verts.append(xyz[1]);
00305           verts.append(xyz[2]);
00306           break;
00307         case 1:
00308           // draw a small cross tangent to the surface
00309           cross_prod(perp1, d, xaxis);  // d and xaxis are of length 1
00310           cross_prod(perp2, d, perp1);  // get the other tangent vector
00311           // scale appropriately
00312 #define CROSS_SCALE_FACTOR 0.05f
00313           perp1[0] *= CROSS_SCALE_FACTOR;
00314           perp1[1] *= CROSS_SCALE_FACTOR;
00315           perp1[2] *= CROSS_SCALE_FACTOR;
00316           perp2[0] *= CROSS_SCALE_FACTOR;
00317           perp2[1] *= CROSS_SCALE_FACTOR;
00318           perp2[2] *= CROSS_SCALE_FACTOR;
00319           vec_add(pos1, xyz, perp1);
00320           vec_sub(pos2, xyz, perp1);
00321           verts.append(pos1[0]);
00322           verts.append(pos1[1]);
00323           verts.append(pos1[2]);
00324           verts.append(pos2[0]);
00325           verts.append(pos2[1]);
00326           verts.append(pos2[2]);
00327           vec_add(pos1, xyz, perp2);
00328           vec_sub(pos2, xyz, perp2);
00329           verts.append(pos1[0]);
00330           verts.append(pos1[1]);
00331           verts.append(pos1[2]);
00332           verts.append(pos2[0]);
00333           verts.append(pos2[1]);
00334           verts.append(pos2[2]);
00335           break;
00336         }
00337       }
00338 
00339       if (method == 1) {
00340         cmdLineArray.putdata(&verts[0], verts.num()/6, cmdList);
00341         verts.clear();
00342         continue;
00343       }
00344 
00345       // had to wait to accumulate all the possible vertices
00346       if (method == 2) {
00347         // draw all the connections if both points are used
00348         int a, b;
00349         int offset = 0;
00350         float xyz[2][3];
00351         // go through the dots
00352         for (a=0; a < num_dots; a++) {
00353           if (flgs[a]) {
00354             // if this point is turned on
00355             xyz[0][0] = pos[0] + radius * dots[3*a + 0];
00356             xyz[0][1] = pos[1] + radius * dots[3*a + 1];
00357             xyz[0][2] = pos[2] + radius * dots[3*a + 2];
00358             
00359             // go through the matching connections
00360             while (offset < num_edges && edges[2*offset] == a) {
00361               // is the neighbor turned on?
00362               b = edges[2*offset + 1];
00363               if (flgs[b]) {
00364                 xyz[1][0] = pos[0] + radius * dots[3*b + 0];
00365                 xyz[1][1] = pos[1] + radius * dots[3*b + 1];
00366                 xyz[1][2] = pos[2] + radius * dots[3*b + 2];
00367                 verts.append(xyz[0][0]);
00368                 verts.append(xyz[0][1]);
00369                 verts.append(xyz[0][2]);
00370                 verts.append(xyz[1][0]);
00371                 verts.append(xyz[1][1]);
00372                 verts.append(xyz[1][2]);
00373               }
00374               offset++;
00375             }
00376           } else {
00377             // just go through the connection until the next number
00378             while (offset < num_edges && edges[2*offset] == a) {
00379               offset++;
00380             }
00381           }
00382         } 
00383         cmdLineArray.putdata(&verts[0], verts.num()/6, cmdList);
00384         verts.clear();
00385       } // end of drawing as lines
00386     }
00387   }
00388   delete [] flgs;
00389   if (method == 0) {
00390     cmdPointArray.putdata(&verts[0], &colors[0], 1.0f, 
00391             verts.num()/3, cmdList);
00392   }
00393 }
00394 

Generated on Sat May 26 01:47:55 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002