00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <math.h>
00025 #include "utilities.h"
00026 #include "AtomColor.h"
00027 #include "Scene.h"
00028 #include "DrawRingsUtils.h"
00029
00030
00031
00032
00033
00034 void hotcold_gradient(float pucker_sum, float *rgb) {
00035 vec_zero(rgb);
00036
00037
00038
00039 if (pucker_sum < 0.25) {
00040 rgb[0] = 1.0;
00041 rgb[1] = pucker_sum * 4.0;
00042 rgb[2] = 0.0;
00043 } else if (pucker_sum < 0.5) {
00044 rgb[0] = 1.0 - (pucker_sum - 0.25) * 4.0;
00045 rgb[1] = 1.0;
00046 rgb[2] = 0.0;
00047 } else if (pucker_sum < 0.75) {
00048 rgb[0] = 0.0;
00049 rgb[1] = 1.0;
00050 rgb[2] = (pucker_sum - 0.5) * 4.0;
00051 } else {
00052 rgb[0] = 0.0;
00053 rgb[1] = 1.0 - (pucker_sum - 0.75) * 4.0;
00054 rgb[2] = 1.0;
00055 }
00056
00057 clamp_color(rgb);
00058 }
00059
00060
00061 float hill_reilly_ring_pucker(SmallRing &ring, float *framepos) {
00062 int N = ring.num();
00063
00064
00065 if (N != 5 && N != 6)
00066 return 0.0;
00067
00068 int NP = N-3;
00069 float *X = new float[N*3];
00070 float *r = new float[N*3];
00071 float *a = new float[NP*3];
00072 float *q = new float[NP*3];
00073 float *n = new float[3];
00074 float *p = new float[3];
00075 float *theta = new float[NP];
00076 float pucker_sum;
00077 float max_pucker_sum;
00078 float *atompos;
00079 int curatomid, i, j, k, l;
00080
00081
00082 for (i=0; i<N; i++) {
00083 curatomid = ring[i];
00084 atompos = framepos + 3*curatomid;
00085 X[3*i] = atompos[0];
00086 X[3*i+1] = atompos[1];
00087 X[3*i+2] = atompos[2];
00088 }
00089
00090
00091 for (i=0; i<N; i++) {
00092 j = (i+1) % N;
00093 vec_sub(r+3*i,X+3*j,X+3*i);
00094 }
00095
00096
00097 for (i=0; i<NP; i++) {
00098 k = (2*(i+1)) % N;
00099 j = (2*i) % N;
00100 l = (2*i+1) % N;
00101 vec_sub(a+3*i,X+3*k,X+3*j);
00102 cross_prod(p,r+3*j,r+3*l);
00103 cross_prod(q+3*i,a+3*i,p);
00104 vec_normalize(q+3*i);
00105 }
00106
00107
00108 cross_prod(n,a+3*0,a+3*1);
00109 vec_normalize(n);
00110
00111
00112 pucker_sum = 0.0;
00113 for (i=0; i<NP; i++) {
00114 theta[i] = (VMD_PI/2.0) - acos(dot_prod(q+3*i,n));
00115 pucker_sum += theta[i];
00116 }
00117
00118
00119 max_pucker_sum = NP * 0.6154;
00120 pucker_sum = fabs(pucker_sum)/max_pucker_sum;
00121 pucker_sum = (pucker_sum < 1.0f) ? pucker_sum : 1.0f;
00122
00123 delete [] X;
00124 delete [] r;
00125 delete [] a;
00126 delete [] q;
00127 delete [] n;
00128 delete [] p;
00129 delete [] theta;
00130
00131 return pucker_sum;
00132 }
00133
00134
00135
00136 void hill_reilly_ring_color(SmallRing &ring, float *framepos, float *rgb) {
00137 float pucker_sum = hill_reilly_ring_pucker(ring, framepos);
00138 hotcold_gradient(pucker_sum, rgb);
00139 }
00140
00141 void hill_reilly_ring_colorscale(SmallRing &ring, float *framepos, float vmin, float vmax, const Scene *scene, float *rgb) {
00142 float pucker_sum = hill_reilly_ring_pucker(ring, framepos);
00143
00144
00145
00146
00147 float vscale;
00148 float vrange = vmax - vmin;
00149 if (fabs(vrange) < 0.00001)
00150 vscale = 0.0f;
00151 else
00152 vscale = 1.00001f / vrange;
00153
00154 float level = (pucker_sum - vmin) * vscale;
00155 int colindex = (int)(level * MAPCLRS-1);
00156 if (colindex < 0)
00157 colindex = 0;
00158 else if (colindex >= MAPCLRS)
00159 colindex = MAPCLRS-1;
00160
00161 const float *scrgb = scene->color_value(MAPCOLOR(colindex));
00162
00163 rgb[0] = scrgb[0];
00164 rgb[1] = scrgb[1];
00165 rgb[2] = scrgb[2];
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175 void vec_incr(float sum[3], const float x, const float y, const float z) {
00176 sum[0] += x;
00177 sum[1] += y;
00178 sum[2] += z;
00179 }
00180
00181
00182
00183
00184 void ring_axes(const float * X, const float * Y, const float * Z, int N,
00185 float x[3], float y[3], float z[3]) {
00186 float Rp[3] = {0.0, 0.0, 0.0}; float Rpp[3] = {0.0, 0.0, 0.0};
00187 int j;
00188 for (j=0; j<N; j++) {
00189 float ze_angle = 2.0 * VMD_PI * float(j-1) / float(N);
00190 float ze_sin = sin(ze_angle);
00191 float ze_cos = cos(ze_angle);
00192 vec_incr( Rp, X[j]*ze_sin, Y[j]*ze_sin, Z[j]*ze_sin );
00193 vec_incr( Rpp, X[j]*ze_cos, Y[j]*ze_cos, Z[j]*ze_cos );
00194 }
00195
00196 cross_prod(z, Rp, Rpp);
00197 vec_normalize(z);
00198
00199
00200
00201
00202
00203
00204 float lambda = dot_prod(z, Rp);
00205 y[0] = Rp[0] - z[0]*lambda;
00206 y[1] = Rp[1] - z[1]*lambda;
00207 y[2] = Rp[2] - z[2]*lambda;
00208 vec_normalize(y);
00209 cross_prod(x, y, z);
00210 }
00211
00212
00213
00214 void atom_displ_from_mean_plane(float * X, float * Y, float * Z,
00215 float * displ, int N) {
00216 float cog[3] = {0.0, 0.0, 0.0};
00217 float x_axis[3], y_axis[3], z_axis[3];
00218 int i;
00219
00220
00221 for (i=0; i<N; i++) {
00222 cog[0] += X[i]; cog[1] += Y[i]; cog[2] += Z[i];
00223 }
00224 cog[0] /= float(N);
00225 cog[1] /= float(N);
00226 cog[2] /= float(N);
00227
00228
00229 for (i=0; i<N; i++) {
00230 X[i] -= cog[0];
00231 Y[i] -= cog[1];
00232 Z[i] -= cog[2];
00233 }
00234
00235 ring_axes( X, Y, Z, N, x_axis, y_axis, z_axis );
00236
00237
00238 for (i=0; i<N; i++) {
00239 displ[i] = X[i]*z_axis[0] + Y[i]*z_axis[1] + Z[i]*z_axis[2];
00240 }
00241 }
00242
00243
00244
00245 int cremer_pople_params(int N_ring_atoms, float * displ, float * q,
00246 float * phi, int & m , float & Q) {
00247 int i, j, k;
00248 if (N_ring_atoms<3)
00249 return -1;
00250
00251 float N = float(N_ring_atoms);
00252 phi[0]=0; q[0]=0;
00253
00254
00255 if (fmod(N, 2.0f)==0) {
00256 float sum =0;
00257 m = N_ring_atoms/2 -1;
00258
00259 for (i=0; i<N_ring_atoms; i++)
00260 sum += displ[i]*cos(i*VMD_PI);
00261
00262 q[int(N_ring_atoms/2)-1]=sqrt(1.0/N)*sum;
00263 } else {
00264 m = int(N_ring_atoms-1)/2;
00265 }
00266
00267
00268 for (i=1; i<m; i++) {
00269 float q_cosphi=0, q_sinphi=0;
00270 for (j=0; j<N_ring_atoms; j++) {
00271 q_cosphi += displ[j]*cos(2.0*VMD_PI*float((i+1)*j)/N);
00272 q_sinphi += displ[j]*sin(2.0*VMD_PI*float((i+1)*j)/N);
00273 }
00274
00275 q_cosphi *= sqrt(2.0/N);
00276 q_sinphi *= -sqrt(2.0/N);
00277 phi[i]=atan(q_sinphi/q_cosphi);
00278
00279 if (q_cosphi < 0)
00280 phi[i]+=VMD_PI;
00281 else if (q_sinphi < 0)
00282 phi[i]+=2*VMD_PI;
00283
00284 q[i]=q_cosphi/phi[i];
00285
00286
00287
00288 Q=0.0;
00289 for (k=0; k<N_ring_atoms; k++)
00290 Q+=displ[k]*displ[k];
00291 Q=sqrt(Q);
00292 }
00293
00294 return 1;
00295 }
00296
00297
00298
00299 void cremer_pople_ring_color(SmallRing &ring, float *framepos, float *rgb) {
00300 int N = ring.num();
00301 float *xring = new float[N];
00302 float *yring = new float[N];
00303 float *zring = new float[N];
00304 float *displ = new float[N];
00305 float *q = new float[N];
00306 float *phi = new float[N];
00307 float Q;
00308 int m;
00309 float *atompos;
00310 int curatomid;
00311
00312 vec_zero(rgb);
00313
00314 for (int i=0; i<N; i++) {
00315 curatomid = ring[i];
00316 atompos = framepos + 3*curatomid;
00317 xring[i] = atompos[0];
00318 yring[i] = atompos[1];
00319 zring[i] = atompos[2];
00320 }
00321
00322 atom_displ_from_mean_plane(xring, yring, zring, displ, N);
00323
00324 if (N==6) {
00325 if (cremer_pople_params(N, displ, q, phi, m, Q)) {
00326 float cosTheta = q[2]/Q;
00327 float theta = acos(cosTheta);
00328 float sinTheta = sin(theta);
00329
00330
00331
00332
00333
00334 float intensity = Q;
00335
00336 rgb[0] = fabs(sinTheta)*intensity;
00337 rgb[1] = fabs(cosTheta)*intensity;
00338 rgb[2] = fabs(sin(3*phi[1])*sinTheta)*intensity;
00339 }
00340 } else if (N==5) {
00341 if (cremer_pople_params(N, displ, q, phi, m, Q)) {
00342 rgb[0] = 0;
00343 rgb[1] = 0;
00344 rgb[2] = Q;
00345 }
00346 }
00347
00348
00349 clamp_color(rgb);
00350
00351 delete [] xring;
00352 delete [] yring;
00353 delete [] zring;
00354 delete [] displ;
00355 delete [] q;
00356 delete [] phi;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366 void ribbon_spline(float *pos, const float * const A, const float * const B,
00367 const float * const C, const float * const D, const float t) {
00368 vec_copy(pos,D);
00369 vec_scaled_add(pos,t,C);
00370 vec_scaled_add(pos,t*t,B);
00371 vec_scaled_add(pos,t*t*t,A);
00372 }
00373
00374
00375
00376