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

DrawMolItem2.C

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

Generated on Thu Apr 18 02:44:35 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002