xyz2rgb
|
1crn.rgb000.rgb,
1crn.xyz,
README,
a.out,
bld,
foo.rgb,
hack.pl,
o8000.rgb,
o8a.rgb,
o8a.xyz,
xyz2rgb,
xyz2rgb.c,
|
|
|
/*
* xyz2rgb.c - convert an XYZ file (or a concatenation of several XYZ files)
* to a ImageMagick-readable bitmap file (or several bitmaps)
*
* Orientation: when longitude and latitude are both zero (the default case)
* the camera lies on the x axis. The camera always faces the origin. The z
* axis always points up, and for zero longitude, the y axis points to the
* right. Increasing longitude will swing the camera around toward the y axis.
* There are two other parameters for controlling the camera, which are the
* width of the viewing area (an angle) and the distance from the camera to
* the origin.
*
* The viewing area is always assumed to have an aspect ratio of 4:3.
*
* $Id: xyz2rgb.c,v 1.5 1997/05/22 01:44:01 wware Exp $
*/
#include
#include
#include
#include
char usage_string[] =
"Usage: xyz2rgb.c [options] foo.xyz\n"
"Options:\n"
" -longitude a specify horizontal angle of camera\n"
" -latitude a specify vertical angle of camera\n"
" -distance x specify distance to origin of camera\n"
" -width a specify wide-angleness of camera\n"
" -hsize n specify number of horizontal pixels\n"
" -vsize n specify number of vertical pixels\n"
" -radii [c,v] select covalent/VanDerWaals atomic radii\n"
" -o filename output filename, files will have numbers\n"
" and \".rgb\" appended to their names\n"
;
typedef struct
{
double longitude, latitude, distance, width;
}
camera;
typedef struct
{
unsigned char r, g, b;
double radius;
char name;
}
species;
typedef struct
{
double x, y, z, radius;
species *spc;
}
atom;
#define MAXHSIZE 1000
unsigned char rbuf[MAXHSIZE], gbuf[MAXHSIZE], bbuf[MAXHSIZE];
double xbuf[MAXHSIZE];
species known_species[] =
{
{
255, 255, 255, 1.5, 'H'
}
,
{
128, 128, 128, 1.94, 'C'
}
,
{
255, 0, 0, 1.82, 'O'
}
,
{
0, 0, 255, 1.74, 'N'
}
};
int num_known_species = sizeof (known_species) / sizeof (species);
#ifdef DEBUG
#define H &known_species[0]
#define C &known_species[1]
#define O &known_species[2]
#define N &known_species[3]
atom atoms[] =
{
{
17.047, 14.099, 3.625, 0.0, N
}
,
{
16.967, 12.784, 4.338, 0.0, C
}
,
{
15.685, 12.755, 5.133, 0.0, C
}
,
{
15.268, 13.825, 5.594, 0.0, O
}
,
{
18.170, 12.703, 5.337, 0.0, H
}
,
{
19.334, 12.829, 4.463, 0.0, O
}
,
{
18.150, 11.546, 6.304, 0.0, H
}
,
{
15.115, 11.555, 5.265, 0.0, N
}
,
{
13.856, 11.469, 6.066, 0.0, H
}
,
{
14.164, 10.785, 7.379, 0.0, C
}
,
{
14.993, 9.862, 7.443, 0.0, O
}
,
{
12.732, 10.711, 5.261, 0.0, C
}
,
{
13.308, 9.439, 4.926, 0.0, O
}
,
{
12.484, 11.442, 3.895, 0.0, C
}
,
{
13.488, 11.241, 8.417, 0.0, N
}
,
{
13.660, 10.707, 9.787, 0.0, H
}
,
{
10.646, 8.991, 11.408, 0.0, C
}
,
{
10.654, 8.793, 12.919, 0.0, C
}
,
{
11.659, 8.296, 13.491, 0.0, O
}
,
{
10.057, 7.752, 10.682, 0.0, C
}
,
{
9.837, 8.018, 8.904, 0.0, O
}
,
{
9.561, 9.108, 13.563, 0.0, N
}
,
{
9.448, 9.034, 15.012, 0.0, C
}
};
#else
atom *atoms;
#endif
static void
transform_coords (atom * atm, camera * cam)
{
double angle, tmp, pfactor;
/* rotate by longitude */
angle = cam->longitude;
tmp = atm->x * cos (angle) + atm->y * sin (angle);
atm->y = atm->y * cos (angle) - atm->x * sin (angle);
atm->x = tmp;
/* rotate by longitude */
angle = cam->latitude;
tmp = atm->x * cos (angle) + atm->z * sin (angle);
atm->z = atm->z * cos (angle) - atm->x * sin (angle);
atm->x = tmp;
/* apply perspective */
pfactor = (cam->distance - atm->x) / cam->distance;
pfactor = (pfactor < 0.01) ? 100.0 : (1.0 / pfactor);
atm->y *= pfactor;
atm->z *= pfactor;
atm->radius *= pfactor;
}
static void
render_atom (atom * a, double z, double ymax, int half_hsize)
{
double local_radius, rsq, zsq, y1, y2;
int i, i1, i2;
rsq = a->radius * a->radius;
zsq = (z - a->z) * (z - a->z);
local_radius = rsq - zsq;
if (local_radius < 0.0)
return;
local_radius = sqrt (local_radius);
y1 = a->y - local_radius;
if (y1 > ymax)
return;
y2 = a->y + local_radius;
if (y2 < -ymax)
return;
i1 = (int) (half_hsize * (y1 / ymax));
i2 = (int) (half_hsize * (y2 / ymax));
for (i = i1 + half_hsize; i <= i2 + half_hsize; i++)
{
double y, ysq, xblip;
y = (i - half_hsize) * (ymax / half_hsize);
ysq = (y - a->y) * (y - a->y);
xblip = rsq - ysq - zsq;
if (xblip < 0.0)
continue;
xblip = sqrt (xblip);
if (xbuf[i] < a->x + xblip)
{
double color_intensity = xblip / a->radius;
xbuf[i] = a->x + xblip;
rbuf[i] = (unsigned char) (color_intensity * a->spc->r);
gbuf[i] = (unsigned char) (color_intensity * a->spc->g);
bbuf[i] = (unsigned char) (color_intensity * a->spc->b);
}
}
}
int hsize, vsize, num_atoms;
double ymax, zmax;
camera cam;
void
render_structure (FILE * outf)
{
int i, h, v;
/* center the structure */
{
double xc, yc, zc;
xc = yc = zc = 0.0;
for (i = 0; i < num_atoms; i++)
{
xc += atoms[i].x;
yc += atoms[i].y;
zc += atoms[i].z;
}
xc /= num_atoms;
yc /= num_atoms;
zc /= num_atoms;
for (i = 0; i < num_atoms; i++)
{
atoms[i].x -= xc;
atoms[i].y -= yc;
atoms[i].z -= zc;
}
}
for (i = 0; i < num_atoms; i++)
{
atoms[i].radius = atoms[i].spc->radius;
transform_coords (&atoms[i], &cam);
}
for (v = 0; v < vsize; v++)
{
for (h = 0; h < hsize; h++)
{
/* sky blue background */
rbuf[h] = 192;
gbuf[h] = 192;
bbuf[h] = 255;
xbuf[h] = -10000000000000.0;
}
/* draw atoms */
for (i = 0; i < num_atoms; i++)
{
double z = (-2.0 * zmax / vsize) * v + zmax;
render_atom (&atoms[i], z, ymax, hsize / 2);
}
for (i = 0; i < hsize; i++)
fputc (rbuf[i], outf);
for (i = 0; i < hsize; i++)
fputc (gbuf[i], outf);
for (i = 0; i < hsize; i++)
fputc (bbuf[i], outf);
}
}
int
ouch (char *s)
{
fprintf (stderr, "%s", s);
return 1;
}
char line[200], infname[40], fname_prefix[40], fname[40];
int
main (int argc, char *argv[])
{
int i, j, fn;
FILE *inf, *outf;
/* initialize all options to default values */
cam.longitude = 0.0;
cam.latitude = 0.0;
cam.distance = 30.0;
cam.width = 30.0 * (3.14159 / 180.0);
hsize = 640;
vsize = 480;
infname[0] = '\0';
fname_prefix[0] = '\0';
if (argc < 2)
return ouch (usage_string);
/* collect command line options */
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-longitude") == 0)
{
double tmp;
if (sscanf (argv[++i], "%lf", &tmp) == 1)
cam.longitude = tmp * (3.14159 / 180.0);
}
else if (strcmp (argv[i], "-latitude") == 0)
{
double tmp;
if (sscanf (argv[++i], "%lf", &tmp) == 1)
cam.latitude = tmp * (3.14159 / 180.0);
}
else if (strcmp (argv[i], "-distance") == 0)
{
double tmp;
if (sscanf (argv[++i], "%lf", &tmp) == 1)
cam.distance = tmp;
}
else if (strcmp (argv[i], "-width") == 0)
{
double tmp;
if (sscanf (argv[++i], "%lf", &tmp) == 1)
cam.width = tmp * (3.14159 / 180.0);
}
else if (strcmp (argv[i], "-hsize") == 0)
{
int tmp;
if (sscanf (argv[++i], "%d", &tmp) == 1)
hsize = tmp;
}
else if (strcmp (argv[i], "-vsize") == 0)
{
int tmp;
if (sscanf (argv[++i], "%d", &tmp) == 1)
vsize = tmp;
}
else if (strcmp (argv[i], "-o") == 0)
{
strcpy (fname_prefix, argv[++i]);
}
else
{
strcpy (infname, argv[i]);
}
}
ymax = cam.distance * tan (cam.width);
zmax = (3.0 / 4.0) * ymax;
#ifdef DEBUG
num_atoms = sizeof (atoms) / sizeof (atom);
outf = stdout;
render_structure (outf);
if (outf != stdout)
fclose (outf);
return 0;
#else
if (strlen(infname) == 0)
inf = stdin;
else
inf = fopen(infname, "r");
if (inf == NULL)
return ouch ("Can't open input file\n");
/* find out how many atoms to grab */
fn = 0;
while (fgets (line, 200, inf) != NULL)
{
char *s;
int found;
if (sscanf (line, "%d", &num_atoms) < 1)
return 0;
atoms = malloc (num_atoms * sizeof (atom));
if (atoms == NULL)
return ouch ("Not enough memory for so many atoms!\n");
fgets (line, 200, inf);
for (i = 0; i < num_atoms; i++)
{
fgets (line, 200, inf);
s = line;
while (*s == ' ' || *s == '\t')
s++;
for (j = found = 0; !found && j < num_known_species; j++)
if (*s == known_species[j].name)
{
found = 1;
atoms[i].spc = &known_species[j];
}
if (!found)
atoms[i].spc = &known_species[0];
s++;
while (*s == ' ' || *s == '\t')
s++;
sscanf(s, "%lf %lf %lf", &atoms[i].x, &atoms[i].y, &atoms[i].z);
}
if (strlen(fname_prefix) > 0)
{
sprintf(fname, "%s%03d.rgb", fname_prefix, fn++);
outf = fopen(fname, "w");
}
else
outf = stdout;
if (outf == NULL)
return ouch ("Can't open output file\n");
render_structure (outf);
if (outf != stdout)
fclose (outf);
}
if (inf != stdin)
fclose (inf);
return 0;
#endif
}
|