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

MoleculeGraphics.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: MoleculeGraphics.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.89 $       $Date: 2021/12/21 05:59:15 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Manages a list of graphics objects.  They can be queried and modified.
00019  *  This is for use by the text interface (and perhaps others).
00020  *
00021  ***************************************************************************/
00022 
00023 #include <stdio.h>
00024 #include "MoleculeGraphics.h"
00025 #include "DispCmds.h"
00026 #include "VMDApp.h"
00027 #include "Inform.h"
00028 #include "JString.h"
00029 #include "Scene.h"
00030 #include "utilities.h"
00031 
00032 void MoleculeGraphics::create_cmdlist(void) {
00033   reset_disp_list();
00034   // set the default values
00035   DispCmdTriangle triangle;
00036   DispCmdCylinder cylinder;
00037   DispCmdPoint point;
00038   DispCmdLine line;
00039   DispCmdCone cone;
00040   DispCmdColorIndex color;
00041   DispCmdLineType linetype;
00042   DispCmdLineWidth linewidth;
00043   DispCmdSphere sphere;
00044   DispCmdSphereRes sph_res;
00045   //DispCmdComment comment;
00046 
00047   append(DMATERIALON);
00048   color.putdata(0, cmdList);     // use the first color by default (blue)
00049   int last_res = -1;             // default sphere resolution
00050 
00051   int last_line = ::SOLIDLINE;       // default for lines
00052   linetype.putdata(last_line, cmdList); // solid and
00053   int last_width = 1;
00054   linewidth.putdata(last_width, cmdList);  //  of width 1
00055 
00056   ResizeArray<float> pickpointcoords;
00057   ResizeArray<int> pickpointindices;
00058 
00059   // go down the list and draw things
00060   int num = num_elements();
00061   ShapeClass *shape;
00062   int sidx=0;
00063   while (sidx<num) {
00064     shape = &(shapes[sidx]);
00065 
00066     switch (shape->shape) {
00067       case NONE: {
00068         break;
00069       }
00070 
00071       case POINT: {
00072         append(DMATERIALOFF);
00073         point.putdata(shape->data+0, cmdList);
00074         append(DMATERIALON);
00075         break;
00076       }
00077 
00078       case PICKPOINT: 
00079         pickpointcoords.append3(shape->data);
00080         pickpointindices.append((int)shape->data[3]);
00081         break;
00082 
00083       case LINE: {
00084         append(DMATERIALOFF);
00085         int style = int(shape->data[6]);
00086         int width = int(shape->data[7]);
00087         if (style != last_line) {
00088           linetype.putdata(style, cmdList);
00089           last_line = style;
00090         }
00091         if (width != last_width) {
00092           linewidth.putdata(width, cmdList);
00093           last_width = width;
00094         }
00095         line.putdata(shape->data+0, shape->data+3, cmdList);
00096         append(DMATERIALON);
00097         break;
00098       }
00099 
00100       case TRIANGLE: {
00101         ResizeArray<float> triangle_vert_buffer;
00102         int tricount=0;
00103         while ((sidx<num) && (tricount < 50000000) && (shape->shape == TRIANGLE)) {
00104           triangle_vert_buffer.append9(&shape->data[0]);
00105           tricount++;
00106           sidx++; // go to the next shape/object
00107           shape = &(shapes[sidx]);
00108         }
00109         sidx--; // correct count prior to outer loop increment
00110 
00111         int cnt = triangle_vert_buffer.num() / 9;
00112         if (cnt > 0) {
00113           DispCmdTriMesh::putdata(&triangle_vert_buffer[0], (float *) NULL, 
00114                                   (float *) NULL, cnt, cmdList);
00115         }
00116         break;
00117       }
00118 
00119       case TRINORM: {
00120         triangle.putdata(shape->data+0, shape->data+3 , shape->data+6, 
00121                          shape->data+9, shape->data+12, shape->data+15, cmdList);
00122         break;
00123       }
00124 
00125       case TRICOLOR: {
00126         // compute rgb colors from indices
00127         float colors[9];
00128         for (int i=0; i<3; i++) {
00129           int c = (int)shape->data[18+i];
00130           c = clamp_int(c, 0, MAXCOLORS-1);
00131           vec_copy(colors+3L*i, scene->color_value(c));
00132         }
00133         const float *verts = shape->data+0;
00134         const float *norms = shape->data+9;
00135         int facets[3] = { 0,1,2 };
00136         DispCmdTriMesh::putdata(verts, norms, colors, 3, facets, 1, 0, cmdList);
00137       }
00138       break;
00139 
00140       case CYLINDER: {
00141         cylinder.putdata(shape->data+0, shape->data+3, shape->data[6], 
00142                          int(shape->data[7]), 
00143                          (int (shape->data[8])) ? 
00144                            CYLINDER_TRAILINGCAP | CYLINDER_LEADINGCAP : 0, 
00145                          cmdList);
00146         break;
00147       }
00148 
00149       case CONE: {
00150         cone.putdata(shape->data+0, shape->data+3, shape->data[6], 
00151                      shape->data[8], int(shape->data[7]), cmdList);
00152         break;
00153       }
00154 
00155       case TEXT: {
00156         append(DMATERIALOFF);
00157         DispCmdText text;
00158         text.putdata(shape->data, shapetext[(int)shape->data[5]], shape->data[4], shape->data[3], 0, 0, cmdList);
00159         append(DMATERIALON);
00160         break;
00161       }
00162 
00163       case SPHERETUBE: {
00164         if (!shape->extradata)
00165           break;
00166 
00167         const int numcoords   = int(shape->data[0]);
00168         const int numradii    = int(shape->data[1]);
00169         const float defradius = shape->data[2];
00170 //        const int numcolors   = shape->data[3]);
00171         const int drawtubes   = int(shape->data[4]);
00172         const int res         = int(shape->data[5]);
00173 
00174 #if 0
00175 printf("***** spheretube draw: coords %d rads %d defrad %f cols %d tubes %d res %d\n",
00176        numcoords, numradii, defradius, numcolors, drawtubes, res);
00177 #endif
00178 
00179         const int coordsz = numcoords * 3; 
00180         const int colorsz = numcoords * 3; // we MUST provide per-sphere colors
00181         const float *xyz3fv = (float *) shape->extradata;
00182         const float *rgb3fv = xyz3fv + coordsz;
00183         const float *radii1fv = xyz3fv + coordsz + colorsz;
00184 
00185         // use either a constant color for all spheres, or use a 
00186         // color-per-sphere 
00187         float *colors = NULL;
00188         float *tmpradii = NULL; 
00189         const float *useradii = NULL;
00190         if ((numradii > 1) && (numradii == numcoords)) {
00191           useradii = radii1fv;
00192 // printf("** using radii array radii[0] = %g\n", useradii[0]);
00193         } else {
00194 // printf("** defradius: %f\n", defradius);
00195           tmpradii = new float[numradii];
00196           for (int i=0; i<numcoords; i++) {
00197             tmpradii[i] = defradius;
00198           }
00199           useradii = tmpradii;
00200 // printf("** using defradius radii[0] = %g\n", useradii[0]);
00201         }
00202 
00203         DispCmdSphereArray cmdSphereArray;
00204         cmdSphereArray.putdata(xyz3fv,
00205                                useradii,
00206                                rgb3fv,
00207                                numcoords,
00208                                res,
00209                                cmdList);
00210 
00211         // optionally draw interconnecting tubes
00212         if (drawtubes) {
00213           // if tubes have varying radii, we must draw cones
00214           int i,j;
00215           for (i=0,j=0; i<(numcoords-1); i++,j+=3) {
00216 // XXX we don't handle color-per sphere yet
00217             cone.putdata(xyz3fv+j, xyz3fv+j+3, 
00218                          useradii[i], useradii[i+1], res, cmdList);
00219           }
00220         }
00221 
00222         delete [] tmpradii;
00223         delete [] colors;
00224         break;
00225       }
00226 
00227 
00228 #if 0
00229       // these aren't supported yet
00230       case DBEGINREPGEOMGROUP: {
00231         char *s = (char *) (shape);
00232         beginrepgeomgroup.putdata(s,cmdList);
00233         break;
00234       }
00235 
00236       case DCOMMENT: {
00237         char *s = (char *) (shape);
00238         comment.putdata(s,cmdList);
00239         break;
00240       }
00241 #endif
00242 
00243       case SPHERE: {
00244         int res = int (shape->data[4]);
00245         if (res != last_res) {
00246           sph_res.putdata(res, cmdList);
00247           last_res = res;
00248         }
00249         sphere.putdata(shape->data+0, shape->data[3], cmdList);
00250         break;
00251       }
00252 
00253       case MATERIALS: {
00254         if (shape->data[0] == 0) append(DMATERIALOFF);
00255         else append(DMATERIALON);
00256         break;
00257       }
00258 
00259       case MATERIAL: {
00260         const float *data = shape->data;
00261         cmdList->ambient = data[0];
00262         cmdList->specular = data[1];
00263         cmdList->diffuse = data[2];
00264         cmdList->shininess = data[3];
00265         cmdList->mirror = data[4];
00266         cmdList->opacity = data[5];
00267         cmdList->outline = data[6];
00268         cmdList->outlinewidth = data[7];
00269         cmdList->transmode = data[8];
00270         cmdList->materialtag = (int)data[9];
00271         break;
00272       }
00273 
00274       case COLOR: {
00275         color.putdata(int(shape->data[0]), cmdList);
00276         break;
00277       }
00278 
00279       default:
00280         msgErr << "Sorry, can't draw that" << sendmsg;
00281     }
00282 
00283     sidx++; // go to the next shape/object
00284   }
00285 
00286   // draw the pickpoints if we have any
00287   if (pickpointindices.num() > 0) {
00288     DispCmdPickPointArray pickPointArray;
00289     pickPointArray.putdata(pickpointindices.num(), &pickpointindices[0],
00290                            &pickpointcoords[0], cmdList);
00291   }
00292 
00293   needRegenerate = 0;  // cmdlist has been udpated 
00294 }
00295 
00296 
00297 // resets the {next,max}_{id,index} values after something is added
00298 // returns the value of the new element
00299 int MoleculeGraphics::added(void) {
00300   needRegenerate = 1;
00301   next_index = shapes.num();
00302   int retval = next_id;
00303   if (next_id == max_id) { // this was a new shape
00304     max_id++;
00305   } 
00306   next_id = max_id;
00307   return retval;
00308 }
00309 
00310 
00311 int MoleculeGraphics::add_triangle(const float *x1, const float *x2, const float *x3) {
00312   // save the points
00313   ShapeClass s(TRIANGLE, 9, next_id);
00314   float *data = s.data;
00315   vec_copy(data+0, x1);
00316   vec_copy(data+3, x2);
00317   vec_copy(data+6, x3);
00318   
00319   // new one goes at next_id
00320   if (next_index < num_elements())
00321     shapes[next_index] = s;
00322   else
00323     shapes.append(s);
00324   return added();
00325 }
00326 
00327 
00328 int MoleculeGraphics::add_trinorm(const float *x1, const float *x2, const float *x3,
00329                                   const float *n1, const float *n2, const float *n3) {
00330   // save the points
00331   ShapeClass s(TRINORM, 18, next_id);
00332   float *data = s.data;
00333   vec_copy(data+ 0, x1);
00334   vec_copy(data+ 3, x2);
00335   vec_copy(data+ 6, x3);
00336   
00337   vec_copy(data+ 9, n1);
00338   vec_normalize(data+ 9); // normalize this normal to prevent problems later
00339   vec_copy(data+12, n2);
00340   vec_normalize(data+12); // normalize this normal to prevent problems later
00341   vec_copy(data+15, n3);
00342   vec_normalize(data+15); // normalize this normal to prevent problems later
00343   
00344   // new one goes at next_id
00345   if (next_index < num_elements())
00346     shapes[next_index] = s;
00347   else
00348     shapes.append(s);
00349 
00350   return added();
00351 }
00352 
00353 
00354 int MoleculeGraphics::add_tricolor(const float *x1, const float *x2, const float *x3,
00355                                    const float *n1, const float *n2, const float *n3, int c1, int c2,
00356           int c3) {
00357   ShapeClass s(TRICOLOR, 21, next_id);
00358   float *data = s.data;
00359   vec_copy(data+ 0, x1);
00360   vec_copy(data+ 3, x2);
00361   vec_copy(data+ 6, x3);
00362 
00363   vec_copy(data+ 9, n1);
00364   vec_normalize(data+ 9); // normalize this normal to prevent problems later
00365   vec_copy(data+12, n2);
00366   vec_normalize(data+12); // normalize this normal to prevent problems later
00367   vec_copy(data+15, n3);
00368   vec_normalize(data+15); // normalize this normal to prevent problems later
00369 
00370   data[18] = (float)c1;
00371   data[19] = (float)c2;
00372   data[20] = (float)c3;
00373   
00374   // new one goes at next_id
00375   if (next_index < num_elements())
00376     shapes[next_index] = s;
00377   else
00378     shapes.append(s);
00379 
00380   return added();
00381 }
00382 
00383 
00384 int MoleculeGraphics::add_point(const float *x) {
00385   ShapeClass s(POINT, 3, next_id);
00386   float *data = s.data;
00387   vec_copy(data+0, x);
00388 
00389   if (next_index < num_elements())
00390     shapes[next_index] = s;
00391   else
00392     shapes.append(s);
00393 
00394   return added();
00395 }
00396 
00397 int MoleculeGraphics::add_pickpoint(const float *x) {
00398   ShapeClass s(PICKPOINT, 4, next_id);
00399   float *data = s.data;
00400   vec_copy(data+0, x);
00401   data[3] = (float) next_index; // this will break for anything >= 2^24
00402 
00403   if (next_index < num_elements())
00404     shapes[next_index] = s;
00405   else
00406     shapes.append(s);
00407 
00408   return added();
00409 }
00410 
00411 int MoleculeGraphics::add_line(const float *x1, const float *x2, int style, int width) {
00412   ShapeClass s(LINE, 8, next_id);
00413   float *data = s.data;
00414   vec_copy(data+0, x1);
00415   vec_copy(data+3, x2);
00416   data[6] = float(style) + 0.1f;
00417   data[7] = float(width) + 0.1f;
00418   if (next_index < num_elements())
00419     shapes[next_index] = s;
00420   else
00421     shapes.append(s);
00422   return added();
00423 }
00424 
00425 
00426 int MoleculeGraphics::add_cylinder(const float *x1, const float *x2, float rad,
00427                                    int n, int filled) {
00428   ShapeClass s(CYLINDER, 9, next_id);
00429   float *data = s.data;
00430   vec_copy(data+0, x1);
00431   vec_copy(data+3, x2);
00432   data[6] = rad;
00433   data[7] = float(n) + 0.1f;
00434   data[8] = float(filled) + 0.1f;
00435   
00436   // new one goes at next_id
00437   if (next_index < num_elements())
00438     shapes[next_index] = s;
00439   else
00440     shapes.append(s);
00441   return added();
00442 }
00443 
00444 
00445 int MoleculeGraphics::add_cone(const float *x1, const float *x2, float rad, float radsq, int n) {
00446   // save the points
00447   ShapeClass s(CONE, 9, next_id);
00448   float *data = s.data;
00449   vec_copy(data+0, x1);
00450   vec_copy(data+3, x2);
00451   data[6] = rad;
00452   data[7] = float(n) + 0.1f;
00453   data[8] = radsq;
00454   
00455   // new one goes at next_id
00456   if (next_index < num_elements())
00457     shapes[next_index] = s;
00458   else
00459     shapes.append(s);
00460   return added();
00461 }
00462 
00463 
00464 int MoleculeGraphics::add_sphere(const float *x, float rad, int n) {
00465   ShapeClass s(SPHERE, 5, next_id);
00466   float *data = s.data;
00467   vec_copy(data+0, x);
00468   data[3] = rad;
00469   data[4] = float(n) + 0.1f;
00470   
00471   // new one goes at next_id
00472   if (next_index < num_elements())
00473     shapes[next_index] = s;
00474   else
00475     shapes.append(s);
00476   return added();
00477 }
00478 
00479 
00480 int MoleculeGraphics::add_text(const float *x, const char *text, 
00481                                float size, float thickness) {
00482   ShapeClass s(TEXT, 6, next_id); 
00483   float *data = s.data;
00484   vec_copy(data+0, x);
00485   data[3] = size;
00486   data[4] = thickness;
00487   data[5] = (float)shapetext.num(); // index where the text will be stored
00488   shapetext.append(stringdup(text));
00489   if (next_index < num_elements())
00490     shapes[next_index] = s;
00491   else
00492     shapes.append(s);
00493   return added();
00494 }
00495 
00496 
00497 int MoleculeGraphics::add_spheretube(const int numcoords, const float *xyz3fv, 
00498                                      const int numradii, const float *radii1fv,
00499                                      const int numcolors,
00500                                      const float *rgb3fv, const int *colorids,
00501                                      int drawtubes, int res) {
00502   ShapeClass s(SPHERETUBE, 6, next_id); 
00503   float *data = s.data;
00504   data[0] = float(numcoords);
00505   data[1] = float(numradii);
00506   data[2] = radii1fv[0];  // if numradii == 1, then this is the global radius
00507   data[3] = float(numcolors);    // if numcolors == 0, we pack a 1-color array
00508   data[4] = float(drawtubes);
00509   data[5] = float(res);
00510 
00511   // store bulk coordinates in an attached memory buffer
00512   const int coordsz = numcoords * 3;
00513   const int colorsz = numcoords * 3; // we MUST provide per-sphere colors
00514   float *tmp = (float *) malloc((coordsz + colorsz + numradii) * sizeof(float));
00515   memcpy(tmp, xyz3fv, coordsz * sizeof(float));
00516 
00517   // we must provide full color-per-sphere data presently
00518   if (numcolors < numcoords) {
00519     // use last draw color state, copied to buffer of elements
00520     const float *tc = scene->color_value(colorID);
00521     for (int i=0; i<colorsz; i+=3) {
00522       vec_copy(tmp+coordsz + i, tc);
00523     }
00524   } else {
00525     if (rgb3fv != NULL) {
00526       memcpy(tmp+coordsz, rgb3fv, colorsz * sizeof(float));
00527     } if (colorids != NULL) {
00528       for (int i=0; i<numcolors; i++) {
00529         int c = colorids[i];
00530         c = clamp_int(c, 0, MAXCOLORS-1);
00531         vec_copy(tmp+coordsz + i*3, scene->color_value(c));
00532       }
00533     }
00534   }
00535 
00536   memcpy(tmp+coordsz+colorsz, radii1fv, numradii * sizeof(float));
00537   s.extradata = tmp;
00538 
00539   // new one goes at next_id
00540   if (next_index < num_elements())
00541     shapes[next_index] = s;
00542   else
00543     shapes.append(s);
00544   return added();
00545 }
00546 
00547 
00548 int MoleculeGraphics::use_materials(int yes_no) {
00549   ShapeClass s(MATERIALS, 1, next_id);
00550   float *data = s.data;
00551   data[0] = (float) yes_no;
00552   if (next_index < num_elements())
00553     shapes[next_index] = s;
00554   else
00555     shapes.append(s);
00556   return added();
00557 }
00558 
00559 
00560 int MoleculeGraphics::use_material(const Material *mat) {
00561   ShapeClass s(MATERIAL, 10, next_id);
00562   float *data = s.data;
00563   data[0] = mat->ambient;
00564   data[1] = mat->specular;
00565   data[2] = mat->diffuse;
00566   data[3] = mat->shininess;
00567   data[4] = mat->mirror;
00568   data[5] = mat->opacity;
00569   data[6] = mat->outline;
00570   data[7] = mat->outlinewidth;
00571   data[8] = mat->transmode;
00572   data[9] = (float)mat->ind;
00573 
00574   if (next_index < num_elements())
00575     shapes[next_index] = s;
00576   else
00577     shapes.append(s);
00578   return added();
00579 }
00580 
00581 
00582 // do this based on the index
00583 int MoleculeGraphics::use_color(int index) {
00584   colorID = index; // record most recently set color index
00585 
00586   ShapeClass s(COLOR, 1, next_id);
00587   float *data = s.data;
00588   data[0] = float(index) + 0.1f; // just to be on the safe side for rounding
00589   if (next_index < num_elements())
00590     shapes[next_index] = s;
00591   else
00592     shapes.append(s);
00593   return added();
00594 }
00595 
00596 
00597 // return the index in the array, or -1 if it doesn't exist
00598 int MoleculeGraphics::index_id(int find_id) {
00599   // the values in the array are numerically increasing, so I can do
00600   // a binary search.
00601   int max_loc = num_elements()-1;
00602   int min_loc = 0;
00603   if (max_loc < min_loc) {
00604     return -1;
00605   }
00606   int loc = (max_loc + min_loc) / 2;
00607   int id = shapes[loc].id;
00608   while (id != find_id && min_loc < max_loc) {
00609     if (id < find_id) {
00610       min_loc = loc+1;
00611     } else {
00612       max_loc = loc-1;
00613     }
00614     loc = (max_loc + min_loc) / 2;
00615     if (loc < 0) break;
00616     id = shapes[loc].id;
00617   }
00618   // and make sure it is for real
00619   if (id == find_id && shapes[loc].shape != NONE) {
00620     return loc;
00621   }
00622   return -1; // not found
00623 }
00624 
00625 
00626 // delete everything
00627 void MoleculeGraphics::delete_all(void) {
00628   shapes.clear(); 
00629   delete_shapetext();    // since there are no references to it now
00630   delete_count = 0;      // and reset the internal variables
00631   next_index = 0;
00632   next_id = 0;
00633   max_id = 0;
00634   needRegenerate = 1;
00635 }
00636 
00637 
00638 // delete given the id
00639 void MoleculeGraphics::delete_id(int id) {
00640   int index = index_id(id);
00641   if (index < 0) return;
00642   shapes[index].clear();
00643   delete_count++;
00644   if (delete_count > 1/* && 
00645       float(delete_count)/float(num_elements()) > 0.2*/) {
00646     // clear out the deleted elements
00647     int i, j=0, n = num_elements();
00648     // moving from i to j
00649     for (i=0; i<n; i++) {
00650       if (shapes[i].shape != NONE) {
00651         if (i != j) {
00652           shapes[j] = shapes[i];
00653         }
00654         j++;
00655       }
00656     }
00657     i=j;
00658     while (i<n) {
00659       shapes[i].clear();
00660       i++;
00661     }
00662     // remove in reverse order so we don't have to copy anything
00663     for (int k=n-1; k >= j; k--) shapes.remove(k);
00664     delete_count = 0;
00665   }
00666   needRegenerate = 1;
00667   // delete overrides a replace
00668   next_id = max_id;
00669   next_index = num_elements();
00670 }
00671 
00672 
00673 // have the next added shape replace the given element
00674 // returns index
00675 int MoleculeGraphics::replace_id(int id) {
00676   int index = index_id(id);
00677   if (index < 0) return -1;
00678   // if one was already assigned to be replaced, and we want to
00679   // replace another, increase the delete count
00680   if (next_id != max_id) {
00681     delete_count++;
00682   }
00683   // do the replacement
00684   shapes[index].clear();
00685   next_id = id;
00686   next_index = index;
00687   return index;
00688 }
00689   
00690 
00691 const char *MoleculeGraphics::info_id(int id) {
00692   int index = index_id(id);
00693   if (index < 0) return NULL;
00694   ShapeClass *shape;
00695   shape = &(shapes[index]);
00696 
00697   if (graphics_info_xl != NULL)
00698     delete graphics_info_xl;
00699 
00700   switch (shape->shape) {
00701   case NONE: {
00702     graphics_info[0] = '\0';
00703     return graphics_info;
00704   }
00705   case POINT: {
00706     sprintf(graphics_info, "point {%f %f %f}",
00707             shape->data[0], shape->data[1], shape->data[2]);
00708     return graphics_info;
00709   }
00710   case PICKPOINT: {
00711     sprintf(graphics_info, "pickpoint {%f %f %f} %d",
00712             shape->data[0], shape->data[1], shape->data[2], (int)shape->data[3]);
00713     return graphics_info;
00714   }
00715   case LINE: {
00716     sprintf(graphics_info, "line {%f %f %f} {%f %f %f} style %s width %d",
00717             shape->data[0], shape->data[1], shape->data[2], 
00718             shape->data[3], shape->data[4], shape->data[5],
00719             shape->data[6] < 0.5 ? "solid" : "dashed",
00720             int(shape->data[7]));
00721     return graphics_info;
00722   }
00723   case TRIANGLE: {
00724     sprintf(graphics_info, "triangle {%f %f %f} {%f %f %f} {%f %f %f}",
00725             shape->data[0], shape->data[1], shape->data[2], 
00726             shape->data[3], shape->data[4], shape->data[5], 
00727             shape->data[6], shape->data[7], shape->data[8]);
00728     return graphics_info;
00729   }
00730   case TRINORM: {
00731     sprintf(graphics_info, "trinorm {%f %f %f} {%f %f %f} {%f %f %f} "
00732             "{%f %f %f} {%f %f %f} {%f %f %f}",
00733             shape->data[0], shape->data[1], shape->data[2], 
00734             shape->data[3], shape->data[4], shape->data[5], 
00735             shape->data[6], shape->data[7], shape->data[8],
00736             shape->data[9], shape->data[10], shape->data[11], 
00737             shape->data[12], shape->data[13], shape->data[14], 
00738             shape->data[15], shape->data[16], shape->data[17]);
00739     return graphics_info;
00740   }
00741   case TRICOLOR: {
00742     sprintf(graphics_info, "tricolor {%f %f %f} {%f %f %f} {%f %f %f} "
00743             "{%f %f %f} {%f %f %f} {%f %f %f} %d %d %d",
00744             shape->data[0], shape->data[1], shape->data[2], 
00745             shape->data[3], shape->data[4], shape->data[5], 
00746             shape->data[6], shape->data[7], shape->data[8],
00747             shape->data[9], shape->data[10], shape->data[11], 
00748             shape->data[12], shape->data[13], shape->data[14], 
00749             shape->data[15], shape->data[16], shape->data[17],
00750       (int)shape->data[18], (int)shape->data[19], (int)shape->data[20]);
00751     return graphics_info;
00752   }
00753   case CYLINDER: {
00754     sprintf(graphics_info, "cylinder {%f %f %f} {%f %f %f} "
00755             "radius %f resolution %d filled %d",
00756             shape->data[0], shape->data[1], shape->data[2], 
00757             shape->data[3], shape->data[4], shape->data[5], 
00758             shape->data[6], int(shape->data[7]), int(shape->data[8]));
00759     return graphics_info;
00760   }
00761   case CONE: {
00762     sprintf(graphics_info, "cone {%f %f %f} {%f %f %f} "
00763             "radius %f radius2 %f resolution %d",
00764             shape->data[0], shape->data[1], shape->data[2], 
00765             shape->data[3], shape->data[4], shape->data[5], 
00766             shape->data[6], shape->data[8], int(shape->data[7]));
00767     return graphics_info;
00768   }
00769   case SPHERE: {
00770     sprintf(graphics_info, "sphere {%f %f %f} radius %f resolution %d",
00771             shape->data[0], shape->data[1], shape->data[2], 
00772             shape->data[3], int(shape->data[4]));
00773     return graphics_info;
00774   }
00775   case TEXT: {
00776     sprintf(graphics_info, "text {%f %f %f} {%s} size %f thickness %f",
00777             shape->data[0], shape->data[1], shape->data[2],
00778             shapetext[(int)shape->data[5]], shape->data[3], shape->data[4]);
00779     return graphics_info;
00780   }
00781   case SPHERETUBE: {
00782     const int numcoords   = int(shape->data[0]);
00783     const int numradii    = int(shape->data[1]);
00784     const float defradius = shape->data[2];
00785 //    const int numcolors   = int(shape->data[3]);
00786     const int drawtubes   = int(shape->data[4]);
00787     const int res         = int(shape->data[5]);
00788     const int coordsz     = numcoords * 3; 
00789     const int colorsz     = numcoords * 3; // we MUST provide per-sphere colors
00790     const float *xyz3fv = (float *) shape->extradata;
00791     const float *rgb3fv = xyz3fv + coordsz;
00792     const float *radii1fv = xyz3fv + coordsz + colorsz;
00793     int i;
00794 
00795     graphics_info_xl = new JString("spheretube {");
00796     for (i=0; i<coordsz; i+=3) {
00797       sprintf(graphics_info, "{%g %g %g} ", xyz3fv[i], xyz3fv[i+1], xyz3fv[i+2]);
00798       *graphics_info_xl += (const char *) graphics_info;
00799     }    
00800     *graphics_info_xl += "} ";
00801 
00802     if (numradii > 1) {
00803        *graphics_info_xl += "radii {";
00804        for (i=0; i<numcoords; i++) {
00805          sprintf(graphics_info, "%g ", radii1fv[i]);
00806          *graphics_info_xl += (const char *) graphics_info;
00807        }    
00808        *graphics_info_xl += "} ";
00809     } else {
00810        sprintf(graphics_info, "radius %g ", defradius);
00811        *graphics_info_xl += "} ";
00812     }
00813 
00814     // XXX incorrect logging at present
00815     // XXX right now this will result in colorID arrays getting converted
00816     // into RGB values incorrectly, we'll need to store them
00817     *graphics_info_xl += "colors {";
00818     for (i=0; i<colorsz; i+=3) {
00819       sprintf(graphics_info, "{%g %g %g} ", rgb3fv[i], rgb3fv[i+1], rgb3fv[i+2]);
00820       *graphics_info_xl += (const char *) graphics_info;
00821     }    
00822     *graphics_info_xl += "} ";
00823 
00824     if (drawtubes) {
00825       *graphics_info_xl += "drawtubes 1 ";
00826     }
00827 
00828     sprintf(graphics_info, "resolution %d ", res);
00829     *graphics_info_xl += (const char *) graphics_info;
00830     return ((const char *) *graphics_info_xl);
00831   }
00832   case MATERIALS: {
00833     sprintf(graphics_info, "materials %d", int(shape->data[0]));
00834     return graphics_info;
00835   }
00836   case MATERIAL: {
00837     sprintf(graphics_info, "material %d", int(shape->data[9]));
00838     return graphics_info;
00839   }
00840   case COLOR: {
00841     sprintf(graphics_info, "color %d", int(shape->data[0]));
00842     return graphics_info;
00843   }
00844   default:
00845     return "";
00846   }
00847 }
00848 
00849 
00850 // return the center of volume and scaling factor
00851 #define CHECK_RANGE(v)     \
00852 {                          \
00853   if (!found_one) {        \
00854     found_one = 1;         \
00855     minx = maxx = (v)[0];  \
00856     miny = maxy = (v)[1];  \
00857     minz = maxz = (v)[2];  \
00858   } else {                 \
00859     if (minx > (v)[0]) minx = (v)[0];  if (maxx < (v)[0]) maxx = (v)[0]; \
00860     if (miny > (v)[1]) miny = (v)[1];  if (maxy < (v)[1]) maxy = (v)[1]; \
00861     if (minz > (v)[2]) minz = (v)[2];  if (maxz < (v)[2]) maxz = (v)[2]; \
00862   }                        \
00863 }
00864 
00865 
00866 void MoleculeGraphics::find_bounds(void) {
00867   float minx=0.0f, maxx=0.0f;
00868   float miny=0.0f, maxy=0.0f;
00869   float minz=0.0f, maxz=0.0f;
00870   int found_one = 0;
00871   // go down the list and draw things
00872   int num = num_elements();
00873   ShapeClass *shape;
00874   for (int i=0; i<num; i++) {
00875     shape = &(shapes[i]);
00876     switch (shape->shape) {
00877     case NONE: {
00878       break;
00879     }
00880     case POINT: {
00881       CHECK_RANGE(shape->data+0);
00882       break;
00883     }
00884     case PICKPOINT: {
00885       CHECK_RANGE(shape->data+0);
00886       break;
00887     }
00888     case LINE: {
00889       CHECK_RANGE(shape->data+0);
00890       CHECK_RANGE(shape->data+3);
00891       break;
00892     }
00893     case TRIANGLE: {
00894       CHECK_RANGE(shape->data+0);
00895       CHECK_RANGE(shape->data+3);
00896       CHECK_RANGE(shape->data+6);
00897       break;
00898     }
00899     case TRINORM: {
00900       CHECK_RANGE(shape->data+0);
00901       CHECK_RANGE(shape->data+3);
00902       CHECK_RANGE(shape->data+6);
00903       break;
00904     }
00905     case TRICOLOR: {
00906       CHECK_RANGE(shape->data+0);
00907       CHECK_RANGE(shape->data+3);
00908       CHECK_RANGE(shape->data+6);
00909       break;
00910     }
00911     case CYLINDER: {
00912       CHECK_RANGE(shape->data+0);
00913       CHECK_RANGE(shape->data+3);
00914       break;
00915     }
00916     case CONE: {
00917       CHECK_RANGE(shape->data+0);
00918       CHECK_RANGE(shape->data+3);
00919       break;
00920     }
00921     case SPHERE: { // I suppose I should include +/- radius ...
00922       CHECK_RANGE(shape->data+0);
00923       break;
00924     }
00925     case TEXT: {   // I suppose I should include the string length size...
00926       CHECK_RANGE(shape->data+0);
00927       break;
00928     }
00929     case SPHERETUBE: {
00930       int numcoords = int(shape->data[0]);
00931       float lmin[3], lmax[3];
00932       const float *coords = (const float *) shape->extradata;
00933       minmax_3fv_aligned(coords, numcoords, lmin, lmax);
00934       minx = lmin[0];
00935       miny = lmin[1];
00936       minz = lmin[2];
00937       maxx = lmax[0];
00938       maxy = lmax[1];
00939       maxz = lmax[2];
00940       break;
00941     }
00942     default:
00943       break;
00944     }
00945   }
00946 
00947   // compute the values for center of volume center and scale
00948   if (!found_one) {
00949     cov_pos[0] = cov_pos[1] = cov_pos[2];
00950     cov_scale = 0.1f;
00951   } else {
00952     cov_pos[0] = (minx + maxx) / 2.0f;
00953     cov_pos[1] = (miny + maxy) / 2.0f;
00954     cov_pos[2] = (minz + maxz) / 2.0f;
00955     float dx = maxx - minx;
00956     float dy = maxy - miny;
00957     float dz = maxz - minz;
00958     // a bit of sanity check (eg, suppose there is only one point)
00959     if (dx == 0 && dy == 0 && dz == 0) dx = 10;
00960     if (dx > dy) {
00961       if (dx > dz) {
00962         cov_scale = 2.0f / dx;
00963       } else {
00964         cov_scale = 2.0f / dz;
00965       }
00966     } else {
00967       if (dy > dz) {
00968         cov_scale = 2.0f / dy;
00969       } else {
00970         cov_scale = 2.0f / dz;
00971       }
00972     }
00973   }
00974 }
00975 
00976 
00977 void MoleculeGraphics::delete_shapetext() {
00978   for (int i=0; i<shapetext.num(); i++) 
00979     delete [] shapetext[i];
00980 
00981   shapetext.clear();
00982 }
00983 

Generated on Fri Nov 8 02:44:52 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002