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

MeasureSurface.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr                                                                       
00003 *cr            (C) Copyright 1995-2008 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: MeasureSurface.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.4 $       $Date: 2008/05/02 02:41:28 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Code to find surface atoms
00019  ***************************************************************************/
00020 
00021 #include <math.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include "Measure.h"
00025 
00026 class Vector3D;
00027 class IndexList;
00028 class AtomData;
00029 class MolData;
00030 class AtomList;
00031 class AtomGrid;
00032 class GridList;
00033 class AtomGridCell;
00034 
00035 // class Vector3D
00036 // Operations on 3-D double vectors
00037 //
00038 class Vector3D {
00039 public:
00040    const Vector3D operator+(const Vector3D w ) const {
00041       Vector3D v;
00042       v.x = x + w.x;
00043       v.y = y + w.y;
00044       v.z = z + w.z;
00045       return v;
00046    }
00047    
00048    const Vector3D operator-(const Vector3D w ) const {
00049       Vector3D v;
00050       v.x = x - w.x;
00051       v.y = y - w.y;
00052       v.z = z - w.z;
00053       return v;
00054    }
00055    
00056    const Vector3D operator*(double s) const {
00057       Vector3D v;
00058       v.x = s*x;
00059       v.y = s*y;
00060       v.z = s*z;
00061       return v;
00062    }
00063    
00064    double length() const { return sqrt(x*x + y*y + z*z); }
00065    double length2() const { return x*x + y*y + z*z; }
00066    double x,y,z;
00067 };
00068 
00069 Vector3D operator*(double s, Vector3D v) {
00070    v.x *= s;
00071    v.y *= s;
00072    v.z *= s;
00073    return v;
00074 }
00075 
00076 Vector3D operator/(Vector3D v, double s) {
00077    v.x /= s;
00078    v.y /= s;
00079    v.z /= s;
00080    return v;
00081 }
00082 
00083 // class IndexList
00084 // A grow-able list of integers, for holding indices of atoms
00085 //
00086 class IndexList {
00087 public:
00088    IndexList() {
00089       num=0;
00090       maxnum=16;
00091       list = new int[16];
00092    }
00093    
00094    ~IndexList() {
00095       if (list != 0)
00096          delete [] list;
00097    }
00098    
00099    void add(const int val) {
00100       // If we need more space, allocate a new block that is
00101       //  1.5 times larger and copy everything over
00102       if (num == maxnum) {
00103          maxnum = (int)(maxnum * 1.5 + 1);
00104          int* oldlist = list;
00105          list = new int[maxnum];
00106          int i;
00107          for(i=0;i<num;i++) {
00108             list[i] = oldlist[i];
00109          }
00110          delete [] oldlist;
00111       }
00112       
00113       // We should have enough space now, add the value
00114       list[num] = val;
00115       num++;
00116    }
00117    
00118    int size() {
00119       return num;
00120    }
00121    
00122    int get(const int i) const { return list[i]; }
00123    
00124 private:
00125    int num;
00126    int maxnum;
00127    int* list;
00128 };
00129 
00130 // class AtomData
00131 // Store the atom index and coordinate in one object
00132 //
00133 class AtomData {
00134 public:
00135    int index;
00136    Vector3D coord;
00137 };
00138 
00139 // class MolData
00140 // Class for storing and reading in the atom coordinates being processed.
00141 // It also contains the routine for determining surface atoms, once the
00142 // vacuum-grid has been built
00143 //
00144 class MolData {
00145 public:
00146    MolData() {
00147       coords = 0;
00148    }
00149    
00150    ~MolData() {
00151       if ( coords != 0) {
00152          delete [] coords;
00153       }
00154    }
00155    
00156    static MolData* readFile(const char* fname,
00157                             double gridspacing, double radius, double threshold);
00158 
00159    static MolData* readData(const int *indx, const float *coords, const int count,
00160                             const Vector3D o,
00161                             const Vector3D a, const Vector3D b, const Vector3D c,
00162                             const double gridspacing, const double radius, 
00163                             const double threshold,
00164                             const bool periodic);
00165    
00166    void wrapCoords(const AtomGrid* grid);
00167    
00168    AtomList* findAtomsGrid(const AtomGrid* grid);
00169    double getRadius() const { return radius; }
00170    double getActualRadius() const { return actual_radius; }
00171    
00172    double gridspacing;
00173    double radius;
00174    double threshold;
00175    double actual_radius;
00176    Vector3D origin;
00177    Vector3D basisa;
00178    Vector3D basisb;
00179    Vector3D basisc;
00180    int count;
00181    AtomData* coords;
00182    bool periodic;
00183 };
00184 
00185 // class AtomList
00186 // Stores the atoms that are part of the shell, and writes their indices out
00187 // at the end
00188 //
00189 class AtomList {
00190 public:
00191    AtomList(const int sz) {
00192       size = sz;
00193       index_list = new int[sz];
00194       count = 0;
00195    }
00196    
00197    ~AtomList() {
00198       if (index_list != 0) {
00199          delete [] index_list;
00200       }
00201    }
00202    
00203    void add(const int index) { index_list[count] = index; count++; }
00204    
00205    void storeFile(const char* fname) const 
00206    {
00207       FILE* outf = fopen(fname,"w");
00208       if (outf == NULL) {
00209          printf("Couldn't open file %s\n",fname);
00210          exit(-1);
00211       }
00212       
00213       int i;
00214       for(i=0; i < count; i++) {
00215          if (fprintf(outf,"%d\n",index_list[i]) < 0) {
00216             printf("Store file error %d %s\n",i,fname);
00217             exit(-2);
00218          }
00219       }
00220       
00221       fclose(outf);
00222       return;
00223    }
00224    
00225    void storeData(int **surf, int *surf_count) const 
00226    {
00227       *surf_count = count;
00228       *surf = new int[count];
00229       int i;
00230       for(i=0; i < count; i++) {
00231          (*surf)[i] = index_list[i];
00232       }
00233       
00234       return;
00235    }
00236    
00237 private:
00238    int* index_list;
00239    int count;
00240    int size;
00241 };
00242 
00243 // class GridList
00244 // Store a list of grid points, with each grid point identified as a 3-D vector
00245 // of ints
00246 //
00247 class GridList {
00248 public:
00249    GridList(AtomGrid* thegrid, const int gridn)
00250    {
00251       n = gridn;
00252       if (n != 0)
00253          items = new Vector3D[n];
00254       else
00255          items = 0;
00256       
00257       indx = 0;
00258       grid = thegrid;
00259       shuffle_vec = scramble_array(n);
00260    }
00261    
00262    ~GridList() {
00263       if (items != 0)
00264          delete [] items;
00265       if (shuffle_vec != 0)
00266          delete [] shuffle_vec;
00267    }
00268    
00269    int add(const int i, const int j, const int k);
00270    
00271    Vector3D get(const int i) const {
00272       if (i < 0 || i >= n)
00273          throw -1;
00274       
00275       return items[i];
00276    }
00277    
00278    int getNum() const { return indx; }
00279    
00280 private:
00281    int n;
00282    int indx;
00283    AtomGrid* grid;
00284    int* shuffle_vec;
00285    Vector3D* items;
00286    static int* scramble_array(const int n);
00287 };
00288 
00289 // class AtomGridCell
00290 // Divide the grid into a mesh of cubic cells. Each cell contains all the grid
00291 // points for that region, and can produce a list of "set" grid points on
00292 // demand
00293 //
00294 class AtomGridCell {
00295 public:
00296    AtomGridCell(AtomGrid* in_ag, int in_mina, int in_maxa, int in_minb, 
00297                 int in_maxb, int in_minc, int in_maxc)
00298    {
00299       //    std::cout << "New AtomGridCell " << mina << "," << maxa << ","
00300       //      << minb << "," << maxb << ","
00301       //      << minc << "," << maxc << ","
00302       //      << std::endl;
00303       
00304       ag = in_ag;
00305       mina = in_mina;
00306       maxa = in_maxa;
00307       minb = in_minb;
00308       maxb = in_maxb;
00309       minc = in_minc;
00310       maxc = in_maxc;
00311       
00312       na = maxa-mina+1;
00313       nb = maxb-minb+1;
00314       nc = maxc-minc+1;
00315       
00316       noneset = true;
00317       getlistcalled = false;
00318       cellmap = 0;
00319       count=0;
00320       gridlist=0;
00321    }
00322    
00323    ~AtomGridCell()
00324    {
00325       if (cellmap != 0)
00326          delete [] cellmap;
00327    }
00328    
00329    int set(const int i, const int j, const int k);
00330    bool get(const int i, const int j, const int k) const;
00331    const GridList* get_list();
00332    
00333 private:
00334    void build_list();
00335    AtomGrid* ag;
00336    int mina;
00337    int maxa;
00338    int minb;
00339    int maxb;
00340    int minc;
00341    int maxc;
00342    int na;
00343    int nb;
00344    int nc;
00345    bool noneset;
00346    bool getlistcalled;
00347    bool* cellmap;
00348    int count;
00349    GridList* gridlist;
00350 };
00351 
00352 // class AtomGrid
00353 // Build and maintain a grid of boolean values for the entire space
00354 //
00355 class AtomGrid {
00356 public:
00357    AtomGrid(const MolData* mdata);
00358    
00359    ~AtomGrid() {
00360       int i,j,k;
00361       for(i=0; i < cna; i++)
00362          for(j=0; j < cnb; j++)
00363             for(k=0; k < cnc; k++) {
00364                delete cellgrid[((i*cnb)+j)*cnc+k];
00365             }
00366       delete [] cellgrid;
00367       delete [] celli;
00368       delete [] cellj;
00369       delete [] cellk;
00370    }
00371    
00372    // get(const int i, const int j, const int k)
00373    // Returns the state (true/false) of grid point (i,j,k)
00374    //
00375    bool get(const int i, const int j, const int k) const 
00376    {
00377       // Find which cell we need, then get the value from that cell
00378       bool ret;
00379       if (i >= 0 && i < na && j >= 0 && j < nb && k >= 0 && k < nc) {
00380          const int ii = celli[i];
00381          const int jj = cellj[j];
00382          const int kk = cellk[k];
00383          const int indx = ((ii*cnb)+jj)*cnc+kk;
00384          ret = cellgrid[indx]->get(i,j,k);
00385       } else {
00386          ret = false;
00387       }
00388       return ret;
00389    }
00390    
00391    // set(const int i, const int j, const int k)
00392    // Set grid point (i,j,k) true. Default is false
00393    //
00394    int set(const int i, const int j, const int k) {
00395       //    std::cout << "set called " << i << "," << j << "." << k << std::endl;
00396       if ( i < 0 || i >= na || j < 0 || j >= nb || k < 0 || k >= nc )
00397          return -1;
00398       
00399       const int ii = celli[i];
00400       const int jj = cellj[j];
00401       const int kk = cellk[k];
00402       return cellgrid[((ii*cnb)+jj)*cnc+kk]->set(i,j,k);
00403    }
00404    
00405    // get_ijk(const Vector3D vv) const
00406    // Convert the real coordinates vv to grid coordinate space.
00407    // The grid coordinates may have a decimal component, indicating
00408    // where it falls within the grid block.
00409    //
00410    Vector3D get_ijk(const Vector3D vv) const 
00411    {
00412       Vector3D ijk;
00413       const Vector3D v = vv - origin;
00414       //    std::cout << "Pos = " << v.x << " " << v.y << " " << v.z
00415       //               << "---" << vv.x << " " << vv.y << " " << vv.z << std::endl;
00416       
00417       ijk.x = (inv_abc[0][0] * v.x + inv_abc[0][1] * v.y + inv_abc[0][2] * v.z)
00418          * na;
00419       ijk.y = (inv_abc[1][0] * v.x + inv_abc[1][1] * v.y + inv_abc[1][2] * v.z)
00420          * nb;
00421       ijk.z = (inv_abc[2][0] * v.x + inv_abc[2][1] * v.y + inv_abc[2][2] * v.z)
00422          * nc;
00423       
00424       return ijk;
00425    }
00426    
00427    // get_cijk(const Vector3D vv, int& i, int& j int& k) const
00428    // Convert the real coordinates vv to grid coordinate space, then determine
00429    // the coordinates of the cell which owns that grid point, and return
00430    // those coordinates in i, j, k
00431    //
00432    void get_cijk(const Vector3D vv, int& i, int& j, int& k) const 
00433    {
00434       Vector3D ijk = get_ijk(vv);
00435       
00436       ijk.x = fmod(ijk.x,na);
00437       if (ijk.x < 0)
00438          ijk.x += na;
00439       ijk.y = fmod(ijk.y,nb);
00440       if (ijk.y < 0)
00441          ijk.y += nb;
00442       ijk.z = fmod(ijk.z,nc);
00443       if (ijk.z < 0)
00444          ijk.z += nc;
00445       
00446       i = celli[(int)(floor(ijk.x))];
00447       j = cellj[(int)(floor(ijk.y))];
00448       k = cellk[(int)(floor(ijk.z))];
00449       return;
00450    }
00451    
00452    // get_xyz(const Vector3D ijk) const
00453    // Convert the grid coordinates ijk to real coordinates
00454    // The grid coordinates may have a decimal component, indicating
00455    // where it falls within the grid block.
00456    //
00457    Vector3D get_xyz(const Vector3D ijk) const
00458    {
00459       Vector3D v = grida * ijk.x / na + gridb * ijk.y / nb + gridc * ijk.z / nc 
00460       + origin;
00461       return v;
00462    }
00463    
00464    // get_xyz(const int i, const int j, const int k) const
00465    // Convert the grid coordinates ijk to real coordinates
00466    // The real coordinates returned are for the center of the grid block
00467    //
00468    Vector3D get_xyz(const int i, const int j, const int k) const 
00469    {
00470       const double id = (i+0.5) / na;
00471       const double jd = (j+0.5) / nb;
00472       const double kd = (k+0.5) / nc;
00473       
00474       Vector3D v = grida * id + gridb * jd + gridc * kd + origin;
00475       return v;
00476    }
00477    
00478    // get_cell(const int i, const int j, const int k) const
00479    // Convert the grid coordinates ijk to real coordinates
00480    // The real coordinates returned are for the center of the grid block
00481    //
00482    const GridList* get_cell(const int i, const int j, const int k) const
00483    {
00484       if (i>=0 && i<cna && j>=0 && j<cnb && k>=0 && k<cnc) {
00485          return cellgrid[((i*cnb)+j)*cnc+k]->get_list();
00486       } 
00487       return 0;
00488    }
00489    
00490    Vector3D wrap_xyz(const Vector3D xyz) const
00491    {
00492       Vector3D gridcoord = get_ijk(xyz);
00493       gridcoord.x = fmod(gridcoord.x,na);
00494       if (gridcoord.x < 0)
00495          gridcoord.x += na;
00496       gridcoord.y = fmod(gridcoord.y,nb);
00497       if (gridcoord.y < 0)
00498          gridcoord.y += nb;
00499       gridcoord.z = fmod(gridcoord.z,nc);
00500       if (gridcoord.z < 0)
00501          gridcoord.z += nc;
00502       
00503       const Vector3D ret = get_xyz(gridcoord);
00504       //    if (gc2.x != gridcoord.x || gc2.y != gridcoord.y || gc2.z != gridcoord.z) {
00505       //      printf("gc2 %f %f %f grid %f %f %f ret %f %f %f\n",
00506       //        gc2.x,gc2.y,gc2.z,gridcoord.x,
00507       //        gridcoord.y,gridcoord.z,ret.x,ret.y,ret.z);
00508       //    }
00509       return ret;
00510    }
00511    
00512    int get_na() const { return na; }
00513    int get_nb() const { return nb; }
00514    int get_nc() const { return nc; }
00515    
00516    int get_cna() const { return cna; }
00517    int get_cnb() const { return cnb; }
00518    int get_cnc() const { return cnc; }
00519    
00520    Vector3D findAtomBox(const double radius) const;
00521    void build(const MolData* mol_data);
00522    void store(char* fname);
00523    void print();
00524    static int* scramble_array(const int n);
00525    
00526 private:
00527       void Inverse3(const double m[3][3], double inv[3][3]) const;
00528    double Cofactor3(const double mat[3][3],const int i, const int j) const;
00529    
00530    
00531    Vector3D origin;
00532    Vector3D grida;
00533    Vector3D gridb;
00534    Vector3D gridc;
00535    double inv_abc[3][3];
00536    int na;
00537    int nb;
00538    int nc;
00539    
00540    int cna;
00541    int cnb;
00542    int cnc;
00543    AtomGridCell** cellgrid;
00544    int* celli;
00545    int* cellj;
00546    int* cellk;
00547    bool periodic;
00548 };
00549 
00550 MolData* MolData::readFile(const char* fname,
00551                            double gridspacing, double radius, double threshold)
00552 {
00553    MolData *data = new MolData;
00554    data->gridspacing = gridspacing;
00555    data->radius = radius;
00556    data->threshold = threshold;
00557    data->actual_radius = radius+threshold;
00558    
00559    
00560    FILE* inpf = fopen(fname,"r");
00561    if (inpf == NULL) {
00562       printf("Couldn't open file %s\n",fname);
00563       exit(-1);
00564    }
00565    
00566    int n_read=0;
00567    n_read += fscanf(inpf,"%lf %lf %lf",
00568                     &(data->origin.x),&(data->origin.y),&(data->origin.z)); 
00569    n_read += fscanf(inpf,"%lf %lf %lf",
00570                     &(data->basisa.x),&(data->basisa.y),&(data->basisa.z)); 
00571    n_read += fscanf(inpf,"%lf %lf %lf",
00572                     &(data->basisb.x),&(data->basisb.y),&(data->basisb.z)); 
00573    n_read += fscanf(inpf,"%lf %lf %lf",
00574                     &(data->basisc.x),&(data->basisc.y),&(data->basisc.z));
00575    n_read += fscanf(inpf,"%d",&(data->count));
00576    
00577    if (n_read != 13) {
00578       printf("Error reading header (%d)",n_read);
00579       exit(-2);
00580    }
00581    
00582    data->coords = new AtomData[data->count];
00583    int i;
00584    for(i=0; i<data->count; i++) {
00585       n_read = fscanf(inpf,"%d %lf %lf %lf",
00586                       &(data->coords[i].index),
00587                       &(data->coords[i].coord.x),
00588                       &(data->coords[i].coord.y),
00589                       &(data->coords[i].coord.z));
00590       if (n_read != 4) {
00591          printf("Error reading atom %d (%d)",i,n_read);
00592          exit(-2);
00593       }
00594    }
00595    fclose(inpf);
00596    return data;
00597 }
00598 
00599 MolData* MolData::readData(const int *indx, const float *coords, 
00600                            const int count,
00601                            const Vector3D o,
00602                            const Vector3D a,
00603                            const Vector3D b,
00604                            const Vector3D c,
00605                            const double gridspacing,
00606                            const double radius,
00607                            const double threshold,
00608                            const bool periodic)
00609 {
00610    MolData *data = new MolData;
00611    data->gridspacing = gridspacing;
00612    data->radius = radius;
00613    data->threshold = threshold;
00614    data->actual_radius = radius+threshold;
00615    data->periodic = periodic;
00616    
00617    data->origin=o;
00618    data->basisa = a;
00619    data->basisb = b;
00620    data->basisc = c;
00621    data->count = count;
00622          
00623    data->coords = new AtomData[data->count];
00624    int i;
00625    int ind=0;
00626    for(i=0; i<data->count; i++) {
00627       data->coords[i].index = indx[i];
00628       data->coords[i].coord.x = coords[ind];
00629       data->coords[i].coord.y = coords[ind+1];
00630       data->coords[i].coord.z = coords[ind+2];
00631       ind += 3;
00632    }
00633    return data;
00634 }
00635 
00636 
00637 void MolData::wrapCoords(const AtomGrid* grid)
00638 {
00639    int i;
00640    for(i=0; i < count; i++) {
00641       coords[i].coord = grid->wrap_xyz(coords[i].coord);
00642    }
00643 }
00644 
00645 int GridList::add(const int i, const int j, const int k) 
00646 {
00647    if (indx >= n)
00648       return -1;
00649    
00650    const int i2 = shuffle_vec[indx];
00651    items[i2].x = i;
00652    items[i2].y = j;
00653    items[i2].z = k;
00654    indx++;
00655    return indx-1;
00656 }
00657 
00658 int AtomGridCell::set(const int i, const int j, const int k) 
00659 {
00660    if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc ) {
00661       return -1;
00662    }
00663    if (getlistcalled) {
00664       return -2;
00665    }
00666    
00667    if (noneset) {
00668       cellmap = new bool[na*nb*nc];
00669       int m;
00670       for(m=na*nb*nc-1; m >= 0; m--)
00671          cellmap[m] = false;
00672       noneset = false;
00673       //    std::cout << "Allocated cell " << i << "," << j << "," << k << std::endl;
00674    }
00675    
00676    const int ii = i - mina;
00677    const int jj = j - minb;
00678    const int kk = k - minc;
00679    const int indx = ((ii*nb)+jj)*nc+kk;
00680    if (!cellmap[indx]) {
00681       count++;
00682    } 
00683    cellmap[indx] = true;
00684    
00685    return 0;
00686 }
00687 
00688 
00689 bool AtomGridCell::get(const int i, const int j, const int k) const
00690 {
00691    //  std::cout << "AtomGridCell::get " << i << "," <<mina << "," << maxa 
00692    //    << std::endl;
00693    
00694    if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc )
00695       return false;
00696 
00697    if (noneset)
00698       return false;
00699    
00700    const int ii = i - mina;
00701    const int jj = j - minb;
00702    const int kk = k - minc;
00703    return cellmap[((ii*nb)+jj)*nc+kk];
00704 }
00705 
00706 const GridList* AtomGridCell::get_list()
00707 {
00708    if (!getlistcalled) {
00709       build_list();
00710    }
00711    return gridlist;
00712 }
00713 
00714 void AtomGridCell::build_list()
00715 {
00716    // Build a list containing only vacuum cells
00717    getlistcalled = true;
00718    int sz = na*nb*nc;
00719    bool* vac = new bool[sz];
00720    int i;
00721    for (i=0; i < sz; i++)
00722       vac[i] = false;
00723    
00724    int tot=0;
00725    int grid_idx = 0;
00726    for(i=mina; i <= maxa; i++) {
00727       //  std::cout << i << std::endl;
00728       int j;
00729       for(j=minb; j <= maxb; j++) {
00730          //      std::cout << j << "," << minc << "-" << maxc << ":";
00731          int k;
00732          for(k=minc; k <= maxc; grid_idx++, k++) {
00733             if (!get(i,j,k)) {
00734                // Optimization:
00735                // If all neighbors are also vacuum, then don't add this one
00736                // since its an interior cell
00737                bool all_vac = true;
00738                if (i > mina && i < maxa 
00739                    && j > minb && j < maxb
00740                    && k > minc && k < maxc) {
00741                   int ii;
00742                   for(ii=-1; ii <= 1; ii++) {
00743                      int jj;
00744                      for(jj=-1; jj <= 1; jj++) {
00745                         int kk;
00746                         for(kk=-1; kk <= 1; kk++) {
00747                            if (get(i+ii,j+jj,k+kk)) {
00748                               //                    std::cout << "Not storing " << i << "," << j << "," << k 
00749                               //                      << std::endl;
00750                               all_vac = false;
00751                               break;
00752                            }
00753                         }
00754                         if (!all_vac)
00755                            break;
00756                      }
00757                      if (!all_vac)
00758                         break;
00759                   }
00760                } else {
00761                   all_vac = false;
00762                }
00763                if (!all_vac) {
00764                   //            std::cout << "Storing " << i << "," << j << "," << k <<std::endl;
00765                   vac[grid_idx] = true;
00766                   tot++;
00767                   //            std::cout << "1";
00768                } // else std::cout << "2";
00769             } // else std::cout << "0";
00770          }
00771          //      std::cout << std::endl;
00772       }
00773    }
00774    gridlist = new GridList(ag,tot);
00775    grid_idx = 0;
00776    int gi;
00777    for(gi=mina; gi <= maxa; gi++) {
00778       int gj;
00779       for(gj=minb; gj <= maxb; gj++) {
00780          int gk;
00781          for(gk=minc; gk <= maxc; grid_idx++, gk++) {
00782             if (vac[grid_idx]) {
00783                //          std::cout << "Adding " << i << "," << j << "," << k <<std::endl;
00784                gridlist->add(gi,gj,gk);
00785             }
00786          }
00787       }
00788    }
00789    //  std::cout << "Gridlist storing " << tot << " of " << sz 
00790    //    << " elements noneset=" << noneset << " count=" << count << std::endl;
00791    delete [] vac;
00792 }
00793 
00794 AtomGrid::AtomGrid(const MolData* mdata)
00795 {
00796    // We'll make a grid with rectangular cells of the specified size
00797    // with a corner at the origin. This means the grid may not exactly
00798    // fit with the periodic box
00799    origin = mdata->origin;
00800    grida = mdata->basisa;
00801    gridb = mdata->basisb;
00802    gridc = mdata->basisc;
00803    na = (int)ceil(mdata->basisa.length() / mdata->gridspacing);
00804    nb = (int)ceil(mdata->basisb.length() / mdata->gridspacing);
00805    nc = (int)ceil(mdata->basisc.length() / mdata->gridspacing);
00806    periodic = mdata->periodic;
00807    
00808    // We'll make a grid with rectangular cells of the specified size
00809    // with a corner at the origin. This means the grid may not exactly
00810    // fit with the periodic box
00811    printf("Grid %d %d %d\n",na,nb,nc);
00812    printf("Origin %f %f %f\n",origin.x,origin.y,origin.z);
00813    
00814    double a[3][3];
00815    
00816    a[0][0] = grida.x;
00817    a[0][1] = gridb.x;
00818    a[0][2] = gridc.x;
00819    a[1][0] = grida.y;
00820    a[1][1] = gridb.y;
00821    a[1][2] = gridc.y;
00822    a[2][0] = grida.z;
00823    a[2][1] = gridb.z;
00824    a[2][2] = gridc.z;
00825    Inverse3(a,this->inv_abc);
00826    
00827    printf("a...\n");
00828    printf("%f %f %f\n",a[0][0],a[0][1],a[0][2]);
00829    printf("%f %f %f\n",a[1][0],a[1][1],a[1][2]);
00830    printf("%f %f %f\n",a[2][0],a[2][1],a[2][2]);
00831    
00832    printf("inv a...\n");
00833    printf("%f %f %f\n",inv_abc[0][0],inv_abc[0][1],inv_abc[0][2]);
00834    printf("%f %f %f\n",inv_abc[1][0],inv_abc[1][1],inv_abc[1][2]);
00835    printf("%f %f %f\n",inv_abc[2][0],inv_abc[2][1],inv_abc[2][2]);
00836    
00837    // Find how many cells to divide this into
00838    Vector3D cellsz = findAtomBox(mdata->getActualRadius());
00839    printf("cellsz=%f, %f, %f\n",cellsz.x,cellsz.y,cellsz.z);
00840    
00841    cna = (int)(floor(na/cellsz.x));
00842    cnb = (int)(floor(nb/cellsz.y));
00843    cnc = (int)(floor(nc/cellsz.z));
00844    if (cna==0) {
00845       cna = 1;
00846    }
00847    if (cnb==0) {
00848       cnb = 1;
00849    }
00850    if (cnc==0) {
00851       cnc = 1;
00852    }
00853    
00854    printf("na=%d, %d, %d\n",na,nb,nc);
00855    printf("cna=%d, %d, %d\n",cna,cnb,cnc);
00856    
00857    // Build the cell grid, dividing grid points roughly-evenly among the cells
00858    cellgrid = new AtomGridCell*[cna*cnb*cnc];
00859    // Storing the cell boundaries will let us find the cells quickly.
00860    celli = new int[na+1];
00861    celli[na] = cna;
00862    cellj = new int[nb+1];
00863    cellj[nb] = cnb;
00864    cellk = new int[nc+1];
00865    cellk[nc] = cnc;
00866    
00867    int* gridi = new int[cna+1];
00868    gridi[cna] = na;
00869    int* gridj = new int[cnb+1];
00870    gridj[cnb] = nb;
00871    int* gridk = new int[cnc+1];
00872    gridk[cnc] = nc;
00873    
00874    // Build the mapping from grid point to cells
00875    int mina = 0;
00876    int maxa;
00877    int i;
00878    for(i=0; i < cna; i++) {
00879       maxa = ((i+1) * na) / cna - 1;
00880       //    std::cout << "minmax=" << mina << "," << maxa << std::endl;
00881       int ii;
00882       for(ii=mina; ii<= maxa; ii++) {
00883          celli[ii] = i;
00884          //      std::cout << "cell[" << ii << "]=" << celli[ii] << std::endl;
00885       }
00886       gridi[i] = mina;
00887       int minb = 0;
00888       int maxb;
00889       int j;
00890       for(j=0; j < cnb; j++) {
00891          maxb = ((j+1) * nb) / cnb - 1;
00892          if (i==0) {
00893             for(int jj=minb; jj<= maxb; jj++)
00894                cellj[jj] = j;
00895          }
00896          gridj[j] = minb;
00897          int minc = 0;
00898          int maxc;
00899          int k;
00900          for(k=0; k < cnc; k++) {
00901             maxc = ((k+1) * nc) / cnc - 1;
00902             if (i==0 && j==0) {
00903                for(int kk=minc; kk<= maxc; kk++)
00904                   cellk[kk] = k;
00905             }
00906             gridk[k] = minc;
00907             minc = maxc+1;
00908          }
00909          minb = maxb+1;
00910       }
00911       mina = maxa+1;
00912    }
00913    
00914    // Now create the cells
00915    int ci;
00916    for(ci=0; ci < cna; ci++) {
00917       int cj;
00918       for(cj=0; cj < cnb; cj++) {
00919          int ck;
00920          for(ck=0; ck < cnc; ck++) {
00921             //        std::cout << "cellgrid[" << i <<"," << j << "," << k << "," <<   ((i*cnb)+j)*cnc + k << " addr " << cellgrid << std::endl;
00922             cellgrid[((ci*cnb)+cj) * cnc + ck] 
00923             = new AtomGridCell(this,gridi[ci],gridi[ci+1]-1,
00924                                gridj[cj],gridj[cj+1]-1,
00925                                gridk[ck],gridk[ck+1]-1);
00926          }
00927       }
00928    }
00929    delete[] gridi;
00930    delete[] gridj;
00931    delete[] gridk;
00932 }
00933 
00934 int* GridList::scramble_array(const int n) {
00935    return AtomGrid::scramble_array(n); 
00936 }
00937 
00938 int* AtomGrid::scramble_array(const int n)
00939 {
00940    if (n < 1) return 0;
00941    
00942    int* a = new int[n];
00943    a[0]=n-1;
00944    if (n == 1) return a;
00945    a[1] = 0;
00946    if (n == 2) return a;
00947    
00948    bool* b = new bool[n];
00949    int i;
00950    for(i=0; i<n; i++)
00951       b[i] = true;
00952    
00953    int howmany = 1;
00954    int incr = (n >> 1);
00955    //  std::cout << "n=" << n << " n>>=" << (n >> 1) << std::endl;
00956    
00957    int nxt=2;
00958    while (nxt < n) {
00959       int i;
00960       for (i=0; i < howmany; i++) {
00961          //      std::cout << "n=" << n << " nxt=" << nxt << " i=" << i << " incr=" << incr << " howmany=" << howmany;
00962          int nxtval = a[i+1] + incr;
00963          //      std::cout << "  nxtval=" << nxtval;
00964          if (b[nxtval])  {
00965             a[nxt++] = nxtval;
00966             //        std::cout << " a[" << nxt-1 << "]=" << a[nxt-1];
00967             b[nxtval] = false;
00968          } 
00969          //      std::cout << std::endl;
00970          if (nxt > n-1)
00971             break;
00972       }
00973       howmany <<= 1;
00974       incr >>= 1;
00975       if (incr == 0)
00976          break;
00977    }
00978    for(i=1; i < n; i++) {
00979       if (nxt >= n) break;
00980       if (b[i])
00981          a[nxt++] = i;
00982    }
00983    delete [] b;
00984    
00985    return a;
00986 }
00987 
00988 Vector3D AtomGrid::findAtomBox(const double radius) const
00989 {
00990    // Find the bounding box for the atom radius
00991    Vector3D cornerx[8];
00992    Vector3D dx, dy, dz;
00993    
00994    const Vector3D o = origin;
00995    dx.y = dx.z = dy.x = dy.z = dz.x = dz.y = 0;
00996    dx.x = dy.y = dz.z = radius;
00997    cornerx[0] = o;
00998    cornerx[1] = o + dx;
00999    cornerx[2] = o + dy;
01000    cornerx[3] = o + dz;
01001    cornerx[4] = cornerx[1] + dy;
01002    cornerx[5] = cornerx[1] + dz;
01003    cornerx[6] = cornerx[2] + dz;
01004    cornerx[7] = cornerx[4] + dz;  
01005    
01006    // Find the max i,j,k for those corners
01007    Vector3D ijk = get_ijk(cornerx[0]);
01008    double dimax = ijk.x;
01009    double djmax = ijk.y;
01010    double dkmax = ijk.z;
01011    
01012    int i;
01013    for(i=1; i < 8; i++) {
01014       ijk = get_ijk(cornerx[i]);
01015       if (ijk.x > dimax)
01016          dimax = ijk.x;
01017       if (ijk.y > djmax)
01018          djmax = ijk.y;
01019       if (ijk.z > dkmax)
01020          dkmax = ijk.z;
01021    }
01022    Vector3D vec;
01023    
01024    vec.x = dimax;
01025    vec.y = djmax;
01026    vec.z = dkmax;
01027    
01028    return vec;
01029 }
01030 
01031 void AtomGrid::build(const MolData* mdata)
01032 {
01033    // Fill the grid
01034    // Find the bounding box for the atom radius
01035    Vector3D bb = findAtomBox(mdata->getRadius());
01036    
01037    const int imax = (int)ceil(bb.x);
01038    const int jmax = (int)ceil(bb.y);
01039    const int kmax = (int)ceil(bb.z);
01040    
01041    printf("Box=%d, %d, %d\n",imax,jmax,kmax);
01042    const double rsq = mdata->getRadius() * mdata->getRadius();
01043    int atomi;
01044    for(atomi=0; atomi<mdata->count; atomi++) {
01045       Vector3D atom = mdata->coords[atomi].coord;
01046       //    std::cout << "Checking atom " << atomi << "(" << atom.x << "," << atom.y << "," << atom.z <<std::endl;
01047       Vector3D atomijk = get_ijk(atom);
01048       const int ai = (int)atomijk.x;
01049       const int aj = (int)atomijk.y;
01050       const int ak = (int)atomijk.z;
01051       int i;
01052       for(i=ai-imax; i <= ai+imax; i++) {
01053          int ii = i;
01054          if (i < 0) {
01055            if (periodic) {
01056              ii += na;
01057            } else continue;
01058          } else if (i >= na) {
01059            if (periodic) {
01060              ii -= na;
01061            } else continue;
01062          }
01063          int j;
01064          for(j=aj-jmax; j <= aj+jmax; j++) {
01065             int jj = j;
01066             if (j < 0) {
01067               if (periodic) {
01068                 jj += nb;
01069               } else continue;
01070             } else if (j >= nb) {
01071               if (periodic) {
01072                 jj -= nb;
01073               } else continue;
01074             }
01075             // Do the positive half of the loop. Stop once we get to
01076             // the first cell that is outside the boundary
01077             int k;
01078             for(k=0; k <= kmax; k++) {
01079                int k_no_wrap = ak+k;
01080                int kk = k_no_wrap;
01081                if (k_no_wrap < 0) {
01082                  if (periodic) {
01083                    kk += nc;
01084                  } else continue;
01085                } else if (k_no_wrap >= nc) {
01086                  if (periodic) {
01087                    kk -= nc;
01088                  } else continue;
01089                }
01090                
01091                // If cell is already filled, just continue
01092                if (get(ii,jj,kk))
01093                   continue;
01094                
01095                const Vector3D v = get_xyz(i,j,k_no_wrap);
01096                const Vector3D dv = v - atom;
01097                if (dv.length2() <= rsq) {
01098                   set(ii,jj,kk);
01099                } else {
01100                   break;
01101                }
01102             }
01103             for(k=1; k <= kmax; k++) {
01104                int k_no_wrap = ak-k;
01105                int kk = k_no_wrap;
01106                if (k_no_wrap < 0) {
01107                  if (periodic) {
01108                    kk += nc;
01109                  } else continue;
01110                } else if (k_no_wrap >= nc) {
01111                  if (periodic) {
01112                    kk -= nc;
01113                  } else continue;
01114                }
01115                
01116                // If cell is already filled, just continue
01117                if (get(ii,jj,kk))
01118                   continue;
01119                
01120                const Vector3D v = get_xyz(i,j,k_no_wrap);
01121                const Vector3D dv = v - atom;
01122                if (dv.length2() <= rsq) {
01123                   set(ii,jj,kk);
01124                } else {
01125                   break;
01126                }
01127             }
01128          }
01129       }
01130    }
01131    return;
01132 }
01133 
01134 void AtomGrid::print()
01135 {
01136    int k;
01137    for(k=0;k < nc; k++) {
01138       int i;
01139       for(i=0; i < na; i++) {
01140          printf("%d:",i);
01141          int j;
01142          for(j=0; j < nb; j++) {
01143             if (get(i,j,k))
01144                printf("1");
01145             else printf("0");
01146          }
01147          printf("\n");
01148       }
01149       printf("%d:-------------------------------------------------------\n",k);
01150    }
01151 }
01152 
01153 void AtomGrid::store(char* fname)
01154 {
01155    FILE* outf = fopen(fname,"w");
01156    if (outf == NULL) {
01157       printf("Couldn't open file %s\n",fname);
01158       exit(-1);
01159    }
01160    
01161    int k;
01162    for(k=0;k < nc; k++) {
01163       int i;
01164       for(i=0; i < na; i++) {
01165          int j;
01166          for(j=0; j < nb; j++) {
01167             if (!get(i,j,k)) {
01168                Vector3D v = get_xyz(i,j,k);
01169                if (fprintf(outf,"%f %f %f\n",v.x,v.y,v.z) < 0) {
01170                   printf("Store grid error %s\n",fname);
01171                   exit(-2);
01172                }
01173             }
01174          }
01175       }
01176    }
01177    
01178    fclose(outf);
01179    return;
01180 }
01181 
01182 void AtomGrid::Inverse3(const double m[3][3], double inv[3][3]) const 
01183 {
01184    // Get adjoint matrix : transpose of cofactor matrix
01185    int i,j;
01186    for(i=0; i < 3; i++)
01187       for(j=0; j < 3; j++)
01188          inv[i][j] = Cofactor3(m,i,j);
01189    
01190    // Now divide by the determinant
01191    const double det = m[0][0] * inv[0][0] 
01192       + m[0][1] * inv[1][0]
01193       + m[0][2] * inv[2][0];
01194    
01195    //    if (det == 0) {
01196    //      error "Non-invertible"
01197    //    }
01198    
01199    for(i=0; i < 3; i++)
01200       for(j=0; j < 3; j++)
01201          inv[i][j] /= det;
01202    
01203    return;
01204 }
01205 
01206 double AtomGrid::Cofactor3(const double mat[3][3],
01207                            const int i, const int j) const {
01208    int cols[3][2] = { {1,2}, {0,2}, {0,1}};
01209    
01210    const int row1 = cols[j][0];
01211    const int row2 = cols[j][1];
01212    
01213    const int col1 = cols[i][0];
01214    const int col2 = cols[i][1];
01215    
01216    const double a = mat[row1][col1];
01217    const double b = mat[row1][col2];
01218    const double c = mat[row2][col1];
01219    const double d = mat[row2][col2];
01220    
01221    const double det = a*d-b*c;
01222    if (((i+j) % 2) != 0)
01223       return -det;
01224    else
01225       return det;
01226 }
01227 
01228 AtomList* MolData::findAtomsGrid(const AtomGrid* grid) 
01229 {
01230    // Scan atoms and check adjacent cells
01231    AtomList *al = new AtomList(count);
01232    const double r = getActualRadius();
01233    const double rsq = r*r;
01234    const Vector3D atom_box = grid->findAtomBox(radius);
01235    int atomi;
01236    for(atomi=0; atomi<count; atomi++) {
01237       Vector3D atom = coords[atomi].coord;
01238       //    std::cout << "Checking atom " << atomi << "(" << atom.x << "," << atom.y << "," << atom.z <<std::endl;
01239       int i0, j0, k0;
01240       bool found = false;
01241       
01242       grid->get_cijk(atom,i0,j0,k0);
01243       int di;
01244       bool cell_outside = false;
01245       for(di=-1; !found && di <= 1; di++) {
01246          int ci = i0 + di;
01247          int cna = grid->get_cna();
01248          int wrapi = 0;
01249          if (ci<0) {
01250            ci += cna;
01251            wrapi = grid->get_na();
01252            if (!periodic)
01253              cell_outside = true;
01254          } else if (ci >= cna) {
01255            ci -= cna;
01256            wrapi = -grid->get_na();
01257            if (!periodic)
01258              cell_outside = true;
01259          }
01260          int dj;
01261          for(dj=-1; !found && dj <= 1; dj++) {
01262             int cj = j0 + dj;
01263             int cnb = grid->get_cnb();
01264             int wrapj = 0;
01265             if (cj<0) {
01266               cj += cnb;
01267               wrapj = grid->get_nb();
01268               if (!periodic)
01269                 cell_outside = true;
01270             } else if (cj >= cnb) {
01271               cj -= cnb;
01272               wrapj = grid->get_nb();
01273               if (!periodic)
01274                 cell_outside = true;
01275             }
01276             int dk;
01277             for(dk=-1; !found && dk <= 1; dk++) {
01278                int ck = k0 + dk;
01279                int cnc = grid->get_cnc();
01280                int wrapk = 0;
01281                if (ck<0) {
01282                  ck += cnc;
01283                  wrapk = grid->get_nc();
01284                  if (!periodic)
01285                    cell_outside = true;
01286                } else if (ck >= cnc) {
01287                  ck -= cnc;
01288                  wrapk = -grid->get_nc();
01289                  if (!periodic)
01290                    cell_outside = true;
01291                }
01292                // If the cell is outside the box, then there must be a
01293                // vacuum there
01294                if (!periodic && cell_outside) {
01295                  const Vector3D atom_grid = grid->get_ijk(atom);
01296                  const Vector3D corner0 = atom_grid - atom_box;
01297                  bool addit = false;
01298                  if (corner0.x < 0 || corner0.y < 0 || corner0.z < 0) {
01299                    addit = true;
01300                  } else {
01301                    const Vector3D corner1 = atom_grid + atom_box;
01302                    if (corner1.x >= grid->get_na() 
01303                        || corner1.y >= grid->get_nb() 
01304                        || corner1.z >= grid->get_nc() )
01305                      addit = true;
01306                  }
01307                  if (addit) {
01308                    al->add(coords[atomi].index);
01309                    found = true;
01310                  }
01311                  cell_outside = false;
01312                }
01313                const GridList* list = grid->get_cell(ci,cj,ck);
01314 //             std::cout << "Found " << list->getNum() 
01315 //                       << " atoms in cell " 
01316 //                       << ci << "," << cj << "," << ck << std::endl;
01317                int gli;
01318                for(gli=0; !found && gli < list->getNum(); gli++) {
01319                   Vector3D gridpt = list->get(gli);
01320                   gridpt.x += wrapi;
01321                   gridpt.y += wrapj;
01322                   gridpt.z += wrapk;
01323                   const Vector3D v = grid->get_xyz(gridpt);
01324                   const Vector3D dv = v - atom;
01325                   if (dv.length2() <= rsq) {
01326                      al->add(coords[atomi].index);
01327                      found = true;
01328 //                   std::cout << "Found vac " << gli << std::endl;
01329                   }
01330                }
01331             }
01332          }
01333       }
01334    }
01335    return al;
01336 }
01337 
01338 int msmain(int argc,char *argv[])
01339 {
01340    if ( argc != 6 ) {
01341       printf(
01342              "Usage: %s grid-res vac-radius selection-dist coord-file index-file\n",
01343              argv[0]);
01344       return 0;
01345    }
01346    
01347    double res = strtod(argv[1],NULL); // Max grid resolution
01348    double radius = strtod(argv[2],NULL); // vacuum-sphere/atom mask radius
01349    double select_dist = strtod(argv[3],NULL); // selection distance
01350    
01351    printf("Reading\n");
01352    MolData* mol_data = MolData::readFile(argv[4],res,radius,select_dist);
01353    printf("Building grid\n");
01354    AtomGrid* atom_grid = new AtomGrid(mol_data);
01355    mol_data->wrapCoords(atom_grid);
01356    atom_grid->build(mol_data);
01357    
01358    //  atom_grid->print();
01359    //  atom_grid->store("grid.dat");
01360    
01361    printf("Searching grid\n");
01362    AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01363    printf("Storing\n");
01364    atom_list->storeFile(argv[5]);
01365    
01366    delete atom_list;
01367    delete atom_grid;
01368    delete mol_data;
01369    
01370    return 0;
01371 }
01372 
01373 void measure_surface_int(const double res, const double radius, 
01374                          const double select_dist,
01375                          const bool periodic,
01376                          const double a, const double b, const double c, 
01377                          const double alpha, const double beta, const double gamma,
01378                          int *indices, float *coords, int count,
01379                          int **surf, int *n_surf
01380                          ) 
01381 {
01382    if (periodic)
01383      printf("System periodic\n");
01384    else printf("System not periodic\n");
01385 
01386    printf("Reading\n");
01387    Vector3D uo;
01388    Vector3D ua;
01389    Vector3D ub;
01390    Vector3D uc;
01391    
01392    // Set origin to center of box
01393    double xmin = coords[0];
01394    double xmax = coords[0];
01395    double ymin = coords[1];
01396    double ymax = coords[1];
01397    double zmin = coords[2];
01398    double zmax = coords[2];
01399    int ind;
01400    int i;
01401    for(i=1, ind=3; i < count; i++, ind += 3) {
01402       if (coords[ind] < xmin)
01403          xmin = coords[ind];
01404       if (coords[ind] > xmax)
01405          xmax = coords[ind];
01406       if (coords[ind+1] < ymin)
01407          ymin = coords[ind+1];
01408       if (coords[ind+1] > ymax)
01409          ymax = coords[ind+1];
01410       if (coords[ind+2] < zmin)
01411          zmin = coords[ind+2];
01412       if (coords[ind+2] > zmax)
01413          zmax = coords[ind+2];
01414    }
01415    uo.x = 0.5*(xmin+xmax);
01416    uo.y = 0.5*(ymin+ymax);
01417    uo.z = 0.5*(zmin+zmax);
01418    
01419    double cosbc = cos(DEGTORAD(alpha));
01420    double cosac = cos(DEGTORAD(beta));
01421    double cosab = cos(DEGTORAD(gamma));
01422    double sinab = sin(DEGTORAD(gamma));
01423    ua.x = a; ua.y = 0; ua.z = 0;
01424    ub.x = b * cosab;
01425    ub.y = b * sinab;
01426    ub.z = 0;
01427    // If sinAB is zero, then we can't determine C uniquely since it's defined
01428    // in terms of the angle between A and B.
01429    if (sinab > 0) {
01430       uc.x = cosac;
01431       uc.y = (cosbc - cosac * cosab) / sinab;
01432       uc.z = sqrt(1.0 - uc.x*uc.x - uc.y*uc.y);
01433    }
01434    uc = c * uc;
01435    // Now move origin to the bottom corner
01436    uo = uo - (0.5 * (ua + ub + uc));
01437    
01438    MolData* mol_data = MolData::readData(indices, coords, count,
01439                                          uo, ua, ub, uc,
01440                                          res,radius,select_dist,periodic);
01441    printf("Building grid\n");
01442    AtomGrid* atom_grid = new AtomGrid(mol_data);
01443    mol_data->wrapCoords(atom_grid);
01444    atom_grid->build(mol_data);
01445    
01446    //   atom_grid->print();
01447    //   atom_grid->store("grid.dat");
01448    
01449    printf("Searching grid\n");
01450    AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01451    printf("Storing\n");
01452    atom_list->storeData(surf,n_surf);
01453    
01454    delete atom_list;
01455    delete atom_grid;
01456    delete mol_data;
01457       
01458    return;
01459 }
01460 
01461 int measure_surface(AtomSel *sel, MoleculeList *mlist,
01462                    const float *framepos,
01463                    const double gridsz, 
01464                    const double radius,
01465                    const double depth,
01466                    int **surface, int *n_surf ) {
01467    int i;
01468    
01469    if (!sel)                     return MEASURE_ERR_NOSEL;
01470    if (sel->num_atoms == 0)      return MEASURE_ERR_NOATOMS;
01471    
01472    // compute the axis aligned aligned bounding box for the selected atoms
01473    int sel_count = 0;
01474    for(i=0; i < sel->num_atoms; i++) {
01475       if (sel->on[i]) {
01476          sel_count++;
01477       }
01478    }
01479    int *sel_ind = new int[sel_count];
01480    float *coords = new float[sel_count*3];
01481    int j=0;
01482    int k=0;
01483    int ind=0;
01484    for(i=0; i < sel->num_atoms; i++) {
01485       if (sel->on[i]) {
01486          sel_ind[j++] = i;
01487          coords[k++] = framepos[ind];
01488          coords[k++] = framepos[ind+1];
01489          coords[k++] = framepos[ind+2];
01490       }
01491       ind += 3;
01492    }
01493    
01494    Timestep *ts = sel->timestep(mlist);
01495    double a = ts->a_length;
01496    double b = ts->b_length;
01497    double c = ts->c_length;
01498    double alpha = ts->alpha;
01499    double beta = ts->beta;
01500    double gamma = ts->gamma;
01501    bool periodic = true;
01502    if (a == 0 || b == 0 || c == 0 
01503        || alpha == 0 || beta == 0 || gamma == 0) {
01504      periodic = false;
01505      float min_coord[3];
01506      float max_coord[3];
01507      measure_minmax(sel->num_atoms, sel->on, framepos, NULL, min_coord, max_coord);
01508      a = max_coord[0] - min_coord[0];
01509      b = max_coord[1] - min_coord[1];
01510      c = max_coord[2] - min_coord[2];
01511      alpha = beta = gamma = 90;
01512    }
01513          
01514    printf("Periodic: %f %f %f %f %f %f\n",a,b,c,alpha,beta,gamma);
01515    
01516    measure_surface_int(gridsz, radius, depth, periodic,
01517                        a,b,c,alpha,beta,gamma,
01518                        sel_ind,coords,sel_count,
01519                        surface, n_surf);
01520    
01521    printf("Done!\n");
01522    
01523    return MEASURE_NOERR;
01524 }

Generated on Sat Sep 6 01:26:56 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002