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 Mon Nov 17 02:46:08 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /