/*
Copyright (C) 2001, 2003, 2005 Matthew P. Hodges
This file is part of XMakemol.
XMakemol is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
XMakemol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with XMakemol; see the file COPYING. If not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdio.h>
#include <Xm/Xm.h> /* Needed for globals.h */
#include "globals.h"
#include "bonds.h"
#include "defs.h"
#include "draw.h"
#include "view.h"
#define FIG_DEPTH_RANGE (995)
#define FIG_SCALE (10)
#define FIG_USER_COLOR_OFFSET (32)
static int use_colour;
static double max_depth, min_depth;
static FILE *output;
void convert_to_canvas_coords (double *, double *, Boolean);
double get_atom_radius (int);
double get_h_bond_width (int, int);
int get_no_dashes (void);
double get_z_depth (void);
void update_canvas_bond_points (int, int, Boolean, double);
void update_canvas_hbond_points (int, int, Boolean);
void write_fig_atom (int);
void write_fig_bond (int, int);
void write_fig_hbond (int, int);
void write_fig_preamble (void);
void
write_fig_file (char *filename, Boolean with_colour)
{
int i, si, sj;
struct node *ptr;
use_colour = with_colour;
output = fopen (filename, "w");
write_fig_preamble ();
/* Get min/max depths */
max_depth = -1e20; min_depth = 1e20;
for (i = 0; i < no_atoms; i++)
{
if (atoms[i].z < min_depth) min_depth = atoms[i].z;
if (atoms[i].z > max_depth) max_depth = atoms[i].z;
}
/* Loop over atoms */
depth = get_z_depth ();
for (i = 0; i < no_atoms; i++)
{
si = sorted_atoms[i];
if (atom_flag
&& ((! depth_is_on) || (depth - atoms[si].z > Z_TOL))
&& atoms[si].visi)
{
write_fig_atom (si);
}
/* Loop over bonds */
if (bond_flag)
{
ptr = bond_adjacency_list[si];
while (ptr != NULL)
{
sj = (ptr->v);
if (((! depth_is_on)
|| (((depth - atoms[si].z > Z_TOL)
&& (depth - atoms[sj].z > Z_TOL))))
&& atoms[si].visi
&& atoms[sj].visi
&& (atoms[si].z <= atoms[sj].z))
{
write_fig_bond (si, sj);
}
ptr = ptr->next;
}
}
/* Loop over H-bonds */
if (any_hydrogen && hbond_flag)
{
ptr = hbond_adjacency_list[si];
while (ptr != NULL)
{
sj = (ptr->v);
if (((! depth_is_on)
|| (((depth - atoms[si].z > Z_TOL)
&& (depth - atoms[sj].z > Z_TOL))))
&& atoms[si].visi
&& atoms[sj].visi
&& (atoms[si].z <= atoms[sj].z))
{
write_fig_hbond (si, sj);
}
ptr = ptr->next;
}
}
}
fclose (output);
}
void
write_fig_preamble ()
{
int i, index = FIG_USER_COLOR_OFFSET;
fprintf (output, "#FIG 3.2\n");
fprintf (output, "Landscape\n"); /* orientation */
fprintf (output, "Center\n"); /* justification */
fprintf (output, "Metric\n"); /* units */
fprintf (output, "A4\n"); /* papersize */
fprintf (output, "100.0\n"); /* export/print magnification */
fprintf (output, "Single\n"); /* single page */
fprintf (output, "-2\n"); /* no transparency */
fprintf (output, "# Generated by XMakemol\n"); /* comment */
fprintf (output, "1200 1\n"); /* resolution/origin at lower left
corner */
if (use_colour)
{
for (i = 0; i < no_atom_types; i++)
{
fprintf (output, "%d %d #%02X%02X%02X\n",
0, /* object code (color) */
index, /* color number */
element[atom_types[i]].red / 256,
element[atom_types[i]].green / 256,
element[atom_types[i]].blue / 256);
index++;
}
}
}
void
write_fig_atom (int si)
{
int color;
char label[4] = "", number[8] = "", text[12] = "";
double current_depth;
double radius;
double xyz_in[3], xy_out[2];
radius = get_atom_radius (si);
xyz_in[0] = atoms[si].x;
xyz_in[1] = atoms[si].y;
xyz_in[2] = atoms[si].z;
convert_to_canvas_coords (xyz_in, xy_out, 0);
/* Calculate depth */
current_depth =
2 + FIG_DEPTH_RANGE * (1.0 - ((atoms[si].z - min_depth) /
(max_depth - min_depth)));
/* Set the colour */
if (use_colour)
{
color = FIG_USER_COLOR_OFFSET + atoms[si].type;
}
else
{
color = 7; /* white */
}
fprintf (output, "%d %d %d %d %d %d %d %d %d %3.1f %d %3.1f %d %d %d %d %d %d %d %d\n",
1, /* object_code (ellipse) */
3, /* sub_type (ellipse defined by radius) */
0, /* line_style (solid) */
1, /* line thickness */
0, /* pen color */
color, /* fill color */
(int) current_depth, /* depth */
-1, /* pen style (not used) */
20, /* area fill (full saturation) */
0.0, /* style val (dash length) */
0, /* direction (clockwise) */
0.0, /* angle (full circle) */
(int) (xy_out[0] * FIG_SCALE), /* center_x */
(int) (xy_out[1] * FIG_SCALE), /* center_y */
(int) (radius * FIG_SCALE), /* radius_x */
(int) (radius * FIG_SCALE), /* radius_y */
(int) (xy_out[0] * FIG_SCALE), /* start_x */
(int) (xy_out[1] * FIG_SCALE), /* start_y */
(int) ((xy_out[0] + radius) * FIG_SCALE), /* end_x */
(int) (xy_out[1] * FIG_SCALE)
);
/* Write labels and or symbols */
if (at_nos_flag)
{
sprintf (number, "%d ", si + 1);
}
if (at_sym_flag)
{
sprintf (label, "%s", atoms[si].label);
}
sprintf (text, "%s%s\\001", number, label);
if (strlen (text) > 0)
{
fprintf (output, "%d %d %d %d %d %d %d %f %d %f %f %d %d %s\n",
4, /* object code (text) */
1, /* center justified */
0, /* color (black) */
(int) current_depth - 1, /* depth */
-1, /* pen style (not used) */
0, /* font (default PostScript) */
12, /* font size in points */
0.0, /* angle of text */
1, /* font flags */
0.0, /* height */
0.0, /* length */
(int) (xy_out[0] * FIG_SCALE), /* x */
(int) (xy_out[1] * FIG_SCALE), /* y */
text);
}
}
void
write_fig_bond (int si, int sj)
{
int color;
double current_depth;
update_canvas_bond_points (si, sj, 0, 0.0);
current_depth =
2 + FIG_DEPTH_RANGE * (1.0 - ((atoms[sj].z - min_depth) /
(max_depth - min_depth)));
if (use_colour)
{
/* Draw polygon 0-1-4-5 (see diagram in draw.c) */
color = FIG_USER_COLOR_OFFSET + atoms[si].type;
fprintf (output, "%d %d %d %d %d %d %d %d %d %3.1f %d %d %d %d %d %d\n\t%d %d %d %d %d %d %d %d %d %d\n",
2, /* object_code (polyline) */
1, /* sub_type (polyline) */
0, /* line_style (solid) */
1, /* line_thickness */
0, /* pen color */
color, /* fill color */
(int) current_depth + 1, /* depth */
-1, /* pen style (not used) */
20, /* area fill (full saturation) */
0.0, /* style val (dash length) */
0, /* join style (not used?) */
0, /* cap style (not used?) */
-1, /* radius */
0, /* forward arrow (off) */
0, /* backward arrow (off) */
5, /* number of points */
(int) (canvas_bond_points[0].x * FIG_SCALE),
(int) (canvas_bond_points[0].y * FIG_SCALE),
(int) (canvas_bond_points[1].x * FIG_SCALE),
(int) (canvas_bond_points[1].y * FIG_SCALE),
(int) (canvas_bond_points[4].x * FIG_SCALE),
(int) (canvas_bond_points[4].y * FIG_SCALE),
(int) (canvas_bond_points[5].x * FIG_SCALE),
(int) (canvas_bond_points[5].y * FIG_SCALE),
(int) (canvas_bond_points[0].x * FIG_SCALE),
(int) (canvas_bond_points[0].y * FIG_SCALE)
);
/* Draw polygon 1-2-3-4 (see diagram in draw.c) */
color = FIG_USER_COLOR_OFFSET + atoms[sj].type;
fprintf (output, "%d %d %d %d %d %d %d %d %d %3.1f %d %d %d %d %d %d\n\t%d %d %d %d %d %d %d %d %d %d\n",
2, /* object_code (polyline) */
1, /* sub_type (polyline) */
0, /* line_style (solid) */
1, /* line_thickness */
0, /* pen color */
color, /* fill color */
(int) current_depth + 1, /* depth */
-1, /* pen style (not used) */
20, /* area fill (full saturation) */
0.0, /* style val (dash length) */
0, /* join style (not used?) */
0, /* cap style (not used?) */
-1, /* radius */
0, /* forward arrow (off) */
0, /* backward arrow (off) */
5, /* number of points */
(int) (canvas_bond_points[1].x * FIG_SCALE),
(int) (canvas_bond_points[1].y * FIG_SCALE),
(int) (canvas_bond_points[2].x * FIG_SCALE),
(int) (canvas_bond_points[2].y * FIG_SCALE),
(int) (canvas_bond_points[3].x * FIG_SCALE),
(int) (canvas_bond_points[3].y * FIG_SCALE),
(int) (canvas_bond_points[4].x * FIG_SCALE),
(int) (canvas_bond_points[4].y * FIG_SCALE),
(int) (canvas_bond_points[1].x * FIG_SCALE),
(int) (canvas_bond_points[1].y * FIG_SCALE)
);
}
else
{
/* Draw polygon 0-2-3-5 (see diagram in draw.c) */
fprintf (output, "%d %d %d %d %d %d %d %d %d %3.1f %d %d %d %d %d %d\n\t%d %d %d %d %d %d %d %d %d %d\n",
2, /* object_code (polyline) */
1, /* sub_type (polyline) */
0, /* line_style (solid) */
1, /* line_thickness */
0, /* pen color */
7, /* fill color (white) */
(int) current_depth + 1, /* depth */
-1, /* pen style (not used) */
20, /* area fill (full saturation) */
0.0, /* style val (dash length) */
0, /* join style (not used?) */
0, /* cap style (not used?) */
-1, /* radius */
0, /* forward arrow (off) */
0, /* backward arrow (off) */
5, /* number of points */
(int) (canvas_bond_points[0].x * FIG_SCALE),
(int) (canvas_bond_points[0].y * FIG_SCALE),
(int) (canvas_bond_points[2].x * FIG_SCALE),
(int) (canvas_bond_points[2].y * FIG_SCALE),
(int) (canvas_bond_points[3].x * FIG_SCALE),
(int) (canvas_bond_points[3].y * FIG_SCALE),
(int) (canvas_bond_points[5].x * FIG_SCALE),
(int) (canvas_bond_points[5].y * FIG_SCALE),
(int) (canvas_bond_points[0].x * FIG_SCALE),
(int) (canvas_bond_points[0].y * FIG_SCALE)
);
}
}
void
write_fig_hbond (int si, int sj)
{
double current_depth, current_width;
double hbond_length, dash_length;
double x, y;
update_canvas_hbond_points (si, sj, 0);
x = canvas_hbond_points[0].x - canvas_hbond_points[1].x;
y = canvas_hbond_points[0].y - canvas_hbond_points[1].y;
hbond_length = sqrt ((x * x) + (y * y));
dash_length =
(int) (hbond_length / (2 * get_no_dashes() - 1));
dash_length *= 2.0 / 3.0; /* Why */
/* Draw polygon 0-2-3-5 (see diagram in draw.c) */
current_depth =
2 + FIG_DEPTH_RANGE * (1.0 - ((atoms[sj].z - min_depth) /
(max_depth - min_depth)));
current_width = get_h_bond_width (si, sj);
current_width *= 2.0 / 3.0; /* Why? */
fprintf (output, "%d %d %d %d %d %d %d %d %d %3.1f %d %d %d %d %d %d\n\t%d %d %d %d\n",
2, /* object_code (polyline) */
1, /* sub_type (polyline) */
1, /* line_style (dashed) */
(int) current_width, /* line_thickness */
0, /* pen color */
7, /* fill color (white) */
(int) current_depth + 1, /* depth */
-1, /* pen style (not used) */
20, /* area fill (full saturation) */
dash_length, /* style val (dash length) */
0, /* join style (not used?) */
0, /* cap style (not used?) */
-1, /* radius */
0, /* forward arrow (off) */
0, /* backward arrow (off) */
2, /* number of points */
(int) (canvas_hbond_points[0].x * FIG_SCALE),
(int) (canvas_hbond_points[0].y * FIG_SCALE),
(int) (canvas_hbond_points[1].x * FIG_SCALE),
(int) (canvas_hbond_points[1].y * FIG_SCALE)
);
}
syntax highlighted by Code2HTML, v. 0.9.1