ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/xyz2pov/src/xyz2pov.c
Revision: 60
Committed: Thu Aug 1 21:12:33 2002 UTC (21 years, 11 months ago) by mmeineke
Content type: text/plain
Original Path: branches/mmeineke/xyz2pov/src/xyz2pov.c
File size: 12999 byte(s)
Log Message:
A pair of utilities to turn an xyz file into a sequence of povray rendered images.

File Contents

# Content
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8
9 #include "frameCount.h"
10 #include "atom_parser.h"
11 #include "pov_writer.h"
12
13
14 #define POV_DIR "./pov"
15
16 struct linked_xyz{
17 struct coords *r;
18 struct linked_xyz *next;
19 };
20
21 char *program_name; /*the name of the program */
22 int draw_bonds = 0; /* boolean to draw bonds or not */
23 int draw_hydrogens = 0; /*boolean to draw hydrogens */
24 int draw_atoms = 0; /*boolean to draw atoms */
25
26 void usage(void);
27
28 int main(argc, argv)
29 int argc;
30 char *argv[];
31 {
32
33
34 struct coords *out_coords;
35
36 int i,j; /* loop counters */
37 mode_t dir_mode = S_IRWXU;
38
39 int generate_header = 0; /* boolean for generating the pov ray header */
40 double big_x = 0;
41 double big_y = 0; /* lets me know the biggest x y and z */
42 double big_z = 0;
43 double small_x = 0;
44 double small_y = 0; /* lets me know the smallest x, y, z */
45 double small_z = 0;
46 double rsqr; /* the square of the diagonal */
47 double diagonal; /* the diagonal length of the sim box */
48
49 unsigned int n_atoms; /*the number of atoms in each time step */
50 char read_buffer[120]; /*the line buffer for reading */
51 char *eof_test; /*ptr to see when we reach the end of the file */
52 char *foo; /*the pointer to the current string token */
53 FILE *in_file; /* the input file */
54 FILE *out_file; /*the output file */
55 char *out_prefix = NULL; /*the prefix of the output file */
56 int have_prefix = 0;
57 char out_name[500]; /*the output name */
58 char out_format[1000];
59 char *in_name = NULL; /*the name of the input file */
60 unsigned int n_out = 0; /*keeps track of which output file is being written*/
61 int done;
62 char current_flag;
63 int nFrames;
64 int nZeroes;
65 double count;
66
67 struct linked_xyz *current_frame;
68 struct linked_xyz *temp_frame;
69
70 unsigned int n_interpolate = 0; /* number of frames to interpolate */
71 double dx, dy, dz; /* temp variables for interpolating distances */
72
73 char pov_dir[500]; /* the pov_dir */
74
75 program_name = argv[0]; /*save the program name in case we need it*/
76
77
78 for( i = 1; i < argc; i++){
79
80 if(argv[i][0] =='-'){
81
82 // parse the option
83
84 if(argv[i][1] == '-' ){
85
86 // parse long word options
87
88 fprintf( stderr,
89 "Invalid option \"%s\"\n", argv[i] );
90 usage();
91
92 }
93
94 else{
95
96 // parse single character options
97
98 done = 0;
99 j = 1;
100 current_flag = argv[i][j];
101 while( (current_flag != '\0') && (!done) ){
102
103 switch(current_flag){
104
105 case 'o':
106 // -o <prefix> => the output prefix.
107
108 i++;
109 out_prefix = argv[i];
110 have_prefix = 1;
111 done = 1;
112 break;
113
114 case 'i':
115 // -i <#> => the number to interpolate
116
117 i++;
118 n_interpolate = atoi( argv[i] );
119 done = 1;
120 break;
121
122 case 'H':
123 // -h => generate a pov-ray Header
124
125 generate_header = 1;
126 break;
127
128 case 'h':
129 // -h => draw Hydrogens
130
131 draw_hydrogens = 1;
132 break;
133
134 case 'b':
135 // -b => draw bonds
136
137 draw_bonds = 1;
138 break;
139
140 case 'a':
141 // -a => draw the atoms
142
143 draw_atoms = 1;
144 break;
145
146 default:
147
148 (void)fprintf(stderr, "Bad option \"-%c\"\n", current_flag);
149 usage();
150 }
151 j++;
152 current_flag = argv[i][j];
153 }
154 }
155 }
156
157 else{
158
159 if( in_name != NULL ){
160 fprintf( stderr,
161 "Error at \"%s\", program does not currently support\n"
162 "more than one input file.\n"
163 "\n",
164 argv[i]);
165 usage();
166 }
167
168 in_name = argv[i];
169 }
170 }
171
172 if(in_name == NULL){
173 usage();
174 }
175
176
177
178 in_file = fopen(in_name, "r");
179 if(in_file == NULL){
180 printf("Cannot open file: %s\n", in_name);
181 exit(8);
182 }
183
184
185
186 if(access(POV_DIR, F_OK)){
187 /*create the pov directory*/
188 mkdir(POV_DIR, dir_mode);
189 }
190 strcpy(pov_dir, POV_DIR); strcat(pov_dir, "/");
191
192
193 // initialize atom type parser
194
195 initializeParser();
196
197 // count the number of frames
198
199 printf( "Counting the number of frames..." );
200 fflush(stdout);
201
202 nFrames = frameCount( in_name );
203
204 printf( "done.\n"
205 "%d frames found\n",
206 nFrames);
207 fflush(stdout);
208
209 // create the output string
210
211 nZeroes = 1;
212 count = (double)( nFrames * (n_interpolate+1) );
213 while( count >= 10.0 ){
214 count /= 10.0;
215 nZeroes++;
216 }
217
218 if(!have_prefix){
219 out_prefix = strtok(in_name, ".");
220 }
221
222 sprintf( out_format, "%s%s%%0%dd.pov", pov_dir, out_prefix, nZeroes );
223
224 // start reading the first frame
225
226 eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
227
228 current_frame = (struct linked_xyz *)malloc(sizeof(struct linked_xyz));
229 current_frame->next = NULL;
230
231
232 while(eof_test != NULL){
233
234 (void)sscanf(read_buffer, "%d", &n_atoms);
235 current_frame->r =
236 (struct coords *)calloc(n_atoms, sizeof(struct coords));
237
238 /*read and toss the comment line */
239
240 eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
241 if(eof_test == NULL){
242 printf("error in reading file\n");
243 exit(8);
244 }
245
246 for( i=0; i < n_atoms; i++){
247
248 eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
249 if(eof_test == NULL){
250 printf("error in reading file\n");
251 exit(8);
252 }
253
254 foo = strtok(read_buffer, " ,;\t");
255 (void)strcpy(current_frame->r[i].name, foo); /*copy the atom name */
256
257 /* next we grab the positions */
258
259 foo = strtok(NULL, " ,;\t");
260 if(foo == NULL){
261 printf("error in reading file\n");
262 exit(8);
263 }
264 (void)sscanf(foo, "%lf",&current_frame->r[i].x);
265 if(current_frame->r[i].x > big_x) big_x = current_frame->r[i].x;
266 if(current_frame->r[i].x < small_x) small_x = current_frame->r[i].x;
267
268
269 foo = strtok(NULL, " ,;\t");
270 if(foo == NULL){
271 printf("error in reading file\n");
272 exit(8);
273 }
274 (void)sscanf(foo, "%lf", &current_frame->r[i].y);
275 if(current_frame->r[i].y > big_y) big_y = current_frame->r[i].y;
276 if(current_frame->r[i].y < small_y) small_y = current_frame->r[i].y;
277
278
279 foo = strtok(NULL, " ,;\t");
280 if(foo == NULL){
281 printf("error in reading file\n");
282 exit(8);
283 }
284 (void)sscanf(foo, "%lf", &current_frame->r[i].z);
285 if(current_frame->r[i].z > big_z) big_z = current_frame->r[i].z;
286 if(current_frame->r[i].z < small_z) small_z = current_frame->r[i].z;
287
288 }
289
290 if(n_interpolate && current_frame->next != NULL){
291
292 temp_frame = current_frame->next;
293
294 for(i = 0; i < n_interpolate; i++){
295
296 /* open the new output file */
297
298 sprintf(out_name, out_format, n_out );
299 out_file = fopen(out_name, "w");
300 n_out++;
301 if(out_file == NULL){
302 printf("error opening output file: %s\n", out_name);
303 exit(8);
304 }
305 (void)fprintf(out_file,
306 "// The following script was automatically generated by:\n"
307 "// xyz2pov Copyright 2001 by MATTHEW A. MEINEKE\n"
308 "\n"
309 "#include \"pov_header.pov\"\n"
310 "\n");
311
312 out_coords =
313 (struct coords *)calloc(n_atoms, sizeof(struct coords));
314
315 for(j=0; j < n_atoms; j++){
316 dx = current_frame->r[j].x - temp_frame->r[j].x;
317 dy = current_frame->r[j].y - temp_frame->r[j].y;
318 dz = current_frame->r[j].z - temp_frame->r[j].z;
319
320 dx /= (double)(n_interpolate + 1);
321 dy /= (double)(n_interpolate + 1);
322 dz /= (double)(n_interpolate + 1);
323
324 strcpy(out_coords[j].name, temp_frame->r[j].name);
325 out_coords[j].x = temp_frame->r[j].x + dx * (i+1);
326 out_coords[j].y = temp_frame->r[j].y + dy * (i+1);
327 out_coords[j].z = temp_frame->r[j].z + dz * (i+1);
328 }
329
330 pov_write(out_file, out_coords, n_atoms, draw_hydrogens, draw_bonds,
331 draw_atoms);
332 free(out_coords);
333 (void)fclose(out_file);
334 }
335 }
336
337 /* open the new output file */
338
339 sprintf(out_name, out_format, n_out );
340 out_file = fopen(out_name, "w");
341 n_out++;
342 if(out_file == NULL){
343 printf("error opening output file: %s\n", out_name);
344 exit(8);
345 }
346 (void)fprintf(out_file,
347 "// The following script was automatically generated by:\n"
348 "// xyz2pov Copyright 2001 by MATTHEW A. MEINEKE\n"
349 "\n"
350 "#include \"pov_header.pov\"\n"
351 "\n");
352
353 out_coords =
354 (struct coords *)calloc(n_atoms, sizeof(struct coords));
355
356 for(i = 0; i < n_atoms; i++){
357 strcpy(out_coords[i].name, current_frame->r[i].name);
358 out_coords[i].x = current_frame->r[i].x;
359 out_coords[i].y = current_frame->r[i].y;
360 out_coords[i].z = current_frame->r[i].z;
361 }
362 pov_write(out_file, out_coords, n_atoms, draw_hydrogens, draw_bonds,
363 draw_atoms);
364 free(out_coords);
365
366 (void)fclose(out_file);
367
368 /*free up memory */
369
370 temp_frame = current_frame->next;
371 current_frame->next = NULL;
372
373 if(temp_frame != NULL){
374
375 free(temp_frame->r);
376 free(temp_frame);
377 }
378
379 /* make a new frame */
380
381 temp_frame = (struct linked_xyz *)malloc(sizeof(struct linked_xyz));
382 temp_frame->next = current_frame;
383 current_frame = temp_frame;
384
385 eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
386
387 }
388
389 (void)fclose(in_file);
390
391
392 if(generate_header){
393
394 dx = big_x - small_x;
395 dy = big_y - small_y;
396 dz = big_z - small_z;
397
398 rsqr = dx * dx + dy * dy + dz * dz;
399 diagonal = sqrt(rsqr);
400 diagonal *= 0.5;
401
402 dx /= 2.0;
403 dy /= 2.0;
404 dz /= 2.0;
405
406 dx += small_x;
407 dy += small_y;
408 dz += small_z;
409
410
411 /*note the y and z axis is exchanged for the different coordinate
412 system in pov-ray*/
413
414
415 out_file = fopen("pov_header.pov", "w");
416
417 fprintf(out_file,
418 "// The following script was automatically generated by:\n"
419 "// xyz2pov Copyright 2001 by MATTHEW A. MEINEKE\n"
420 "\n"
421 "\n"
422 "background { rgb <1.0, 1.0, 1.0> }\n"
423 "\n"
424 "\n"
425 );
426
427 fprintf(out_file,
428 "//******************************************************\n"
429 "// Declare the resolution, camera, and light sources.\n"
430 "//******************************************************\n"
431 "\n"
432 "// NOTE: if you plan to render at a different resoltion,\n"
433 "// be sure to update the following two lines to maintain\n"
434 "// the correct aspect ratio.\n"
435 "\n"
436 "#declare Width = 640.0;\n"
437 "#declare Height = 480.0;\n"
438 "#declare Ratio = Width / Height;\n"
439 "\n"
440 "#declare zoom = %lf;\n"
441 "\n"
442 "#declare ATOM_SPHERE_FACTOR = 0.2;\n"
443 "#declare BOND_RADIUS = 0.1;\n"
444 "\n"
445 "camera{\n"
446 " location < %lf, %lf, %lf - zoom>\n"
447 " right < Ratio , 0, 0>\n"
448 " look_at < %lf, %lf, %lf >\n"
449 "}\n"
450 "\n",
451 diagonal,
452 dx, dz, dy,
453 dx, dz, dy);
454
455 fprintf(out_file,
456 "light_source{\n"
457 " < %lf, %lf, %lf - zoom >\n"
458 " rgb < 1.0, 1.0, 1.0 > }\n",
459 dx, dz, dy);
460
461 fprintf(out_file,
462 "light_source{\n"
463 " < %lf - zoom , %lf + zoom, %lf - zoom >\n"
464 " rgb < 1.0, 1.0, 1.0 > }\n"
465 "\n"
466 "\n",
467 dx, dz, dy);
468
469 fprintf(out_file,
470 "//************************************************************\n"
471 "// Set whether or not to rotate the system.\n"
472 "//\n"
473 "// To Rotate, set ROTATE to 1.0 (true),\n"
474 "// Then set the Euler Angles PHI, THETA, and PSI in degrees.\n"
475 "//************************************************************\n"
476 "\n"
477 "#declare ROTATE = 0.0;\n"
478 "#declare PHI = 0.0;\n"
479 "#declare THETA = 0.0;\n"
480 "#declare PSI = 0.0;\n"
481 "\n"
482 "#if(ROTATE)\n"
483 " #declare phi_r = radians(PHI);\n"
484 " #declare theta_r = radians(THETA);\n"
485 " #declare psi_r = radians(PSI);\n"
486 "\n"
487 " #declare A11 = cos(phi_r) * cos(psi_r) - sin(phi_r) * cos(theta_r) * sin(psi_r);\n"
488 " #declare A12 = sin(phi_r) * cos(psi_r) + cos(phi_r) * cos(theta_r) * sin(psi_r);\n"
489 " #declare A13 = sin(theta_r) * sin(psi_r);\n"
490 "\n"
491 " #declare A21 = -cos(phi_r) * sin(psi_r) - sin(phi_r) * cos(theta_r) * cos(psi_r);\n"
492 " #declare A22 = -sin(phi_r) * sin(psi_r) + cos(phi_r) * cos(theta_r) * cos(psi_r);\n"
493 " #declare A23 = sin(theta_r) * cos(psi_r);\n"
494 "\n"
495 " #declare A31 = sin(phi_r) * sin(theta_r);\n"
496 " #declare A32 = -cos(phi_r) * sin(theta_r);\n"
497 " #declare A33 = cos(theta_r);\n"
498 "\n"
499 "#end\n"
500 "\n");
501
502
503 make_header_macros(out_file);
504
505 fclose(out_file);
506 }
507
508 return 0;
509
510 }
511
512
513
514 /***************************************************************************
515 * prints out the usage for the command line arguments, then exits.
516 ***************************************************************************/
517
518 void usage(){
519 (void)fprintf(stderr,
520 "The proper usage is: %s [options] <xyz_file>\n"
521 "\n"
522 "Options:\n"
523 "\n"
524 " -o <prefix> the output file prefix\n"
525 " -H generate a pov-ray header file\n"
526 " -i <#> number of frames to interpolate\n"
527 " -h draw hydrogens\n"
528 " -b draw bonds\n"
529 " -a draw atoms\n"
530 "\n",
531 program_name);
532 exit(8);
533 }