/* 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 #include #include /* 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) ); }