/*
Copyright (C) 2003 by Sean David Fleming
sean@ivec.org
This program 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
of the License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The GNU GPL can also be found at http://www.gnu.org
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <math.h>
#include "gdis.h"
#include "coords.h"
#include "edit.h"
#include "error.h"
#include "interface.h"
#include "matrix.h"
#include "measure.h"
#include "spatial.h"
#include "surface.h"
#include "numeric.h"
#include "morph.h"
#include "opengl.h"
#include "render.h"
#include "select.h"
#include "zone.h"
/* data structures */
extern struct sysenv_pak sysenv;
extern struct elem_pak elements[];
/**********************/
/* debugging routines */
/**********************/
void dump_links(GSList *list)
{
GSList *item;
struct core_pak *core;
struct shel_pak *shell;
for (item=list ; item ; item=g_slist_next(item))
{
core = item->data;
printf("core: %p, shell: %p ", core, core->shell);
P3VEC(" : ", core->x);
}
for (item=list ; item ; item=g_slist_next(item))
{
shell = item->data;
printf("shell: %p, core: %p\n", shell, shell->core);
P3VEC(" : ", shell->x);
}
}
void print_core_list(GSList *list)
{
gint i=0;
GSList *item;
struct core_pak *core;
struct shel_pak *shell;
for (item=list ; item ; item=g_slist_next(item))
{
core = item->data;
/*
if (i==4)
*/
{
printf("[%4s] %1d %1d c %10.4f %10.4f %10.4f : %6.2f\n",
core->atom_label, core->primary, core->orig,
core->x[0], core->x[1], core->x[2], core->charge);
if (core->shell)
{
shell = core->shell;
printf("[%4s] %1d %1d s %10.4f %10.4f %10.4f : %6.2f\n",
shell->shell_label, shell->primary, shell->orig,
shell->x[0], shell->x[1], shell->x[2], shell->charge);
}
}
i++;
}
}
void print_core_list_cart(GSList *list)
{
gint i=0;
GSList *item;
struct core_pak *core;
struct shel_pak *shell;
for (item=list ; item ; item=g_slist_next(item))
{
core = item->data;
/*
if (i==4)
*/
{
printf("[%4s] %1d %1d c %10.4f %10.4f %10.4f : %6.2f\n",
core->atom_label, core->primary, core->orig,
core->rx[0], core->rx[1], core->rx[2], core->charge);
if (core->shell)
{
shell = core->shell;
printf("[%4s] %1d %1d s %10.4f %10.4f %10.4f : %6.2f\n",
shell->shell_label, shell->primary, shell->orig,
shell->rx[0], shell->rx[1], shell->rx[2], shell->charge);
}
}
i++;
}
}
/****************/
/* SPECIAL OBJS */
/****************/
#define DEBUG_INIT 0
void coords_init(gint type, struct model_pak *data)
{
g_return_if_fail(data != NULL);
switch(type)
{
/* atomic coordinates processing */
case INIT_COORDS:
/* find unique elements */
g_slist_free(data->unique_atom_list);
data->unique_atom_list = find_unique(ELEMENT, data);
/* init the charges */
init_model_charges(data);
/* update electrostatic info */
calc_emp(data);
/* repetition here, since there is interdependence */
/* between centroid (coords_center) and latmat (coords_compute) calc */
coords_center(1, data);
coords_compute(data);
case CENT_COORDS:
coords_center(1, data);
case REDO_COORDS:
coords_compute(data);
break;
default:
printf("Unknown object type requested!\n");
}
}
/******************************************/
/* convert fractional coords to cartesian */
/******************************************/
void coords_make_cartesian(struct model_pak *model)
{
GSList *list;
struct core_pak *core;
struct shel_pak *shel;
struct vertex_pak *vec;
g_assert(model != NULL);
/* transform cores */
for (list=model->cores ; list ; list=g_slist_next(list))
{
core = list->data;
vecmat(model->latmat, core->x);
}
/* transform shells */
for (list=model->shels ; list ; list=g_slist_next(list))
{
shel = list->data;
vecmat(model->latmat, shel->x);
}
/* morphology vertices */
for (list=model->vertices ; list ; list=g_slist_next(list))
{
vec = list->data;
vecmat(model->latmat, vec->x);
}
matrix_identity(model->latmat);
matrix_identity(model->ilatmat);
matrix_identity(model->rlatmat);
}
/******************************************/
/* convert cartesian coords to fractional */
/******************************************/
void coords_make_fractional(struct model_pak *model)
{
GSList *list;
struct core_pak *core;
struct shel_pak *shel;
struct vertex_pak *vec;
g_assert(model != NULL);
/* transform cores */
for (list=model->cores ; list ; list=g_slist_next(list))
{
core = list->data;
vecmat(model->ilatmat, core->x);
}
/* transform shells */
for (list=model->shels ; list ; list=g_slist_next(list))
{
shel = list->data;
vecmat(model->ilatmat, shel->x);
}
/* morphology vertices */
for (list=model->vertices ; list ; list=g_slist_next(list))
{
vec = list->data;
vecmat(model->ilatmat, vec->x);
}
}
/*************************************/
/* process coordinate scaling factor */
/*************************************/
void coords_init_units(struct model_pak *model)
{
gdouble scale=1.0;
GSList *list;
struct core_pak *core;
struct shel_pak *shel;
g_assert(model != NULL);
switch (model->coord_units)
{
case BOHR:
scale = AU2ANG;
break;
default:
return;
}
/* transform cores */
for (list=model->cores ; list ; list=g_slist_next(list))
{
core = list->data;
VEC3MUL(core->x, scale);
}
/* transform shells */
for (list=model->shels ; list ; list=g_slist_next(list))
{
shel = list->data;
VEC3MUL(shel->x, scale);
}
}
/********/
/* AXES */
/********/
void make_axes(struct model_pak *data)
{
VEC3SET(data->axes[0].x, 1.0, 0.0, 0.0);
VEC3SET(data->axes[1].x, 0.0, 1.0, 0.0);
VEC3SET(data->axes[2].x, 0.0, 0.0, 1.0);
}
/********/
/* CELL */
/********/
void make_cell(struct model_pak *data)
{
gdouble b, c;
if (!data->periodic)
return;
/* periodicity hacks */
b = (data->periodic < 2) ? 0.0 : 1.0;
c = (data->periodic < 3) ? 0.0 : 1.0;
/* end face 1 */
VEC3SET(data->cell[0].x, 0.0, 0.0, 0.0);
VEC3SET(data->cell[1].x, 0.0, b, 0.0);
VEC3SET(data->cell[2].x, 1.0, b, 0.0);
VEC3SET(data->cell[3].x, 1.0, 0.0, 0.0);
/* end face 2 */
VEC3SET(data->cell[4].x, 0.0, 0.0, c);
VEC3SET(data->cell[5].x, 0.0, b, c);
VEC3SET(data->cell[6].x, 1.0, b, c);
VEC3SET(data->cell[7].x, 1.0, 0.0, c);
}
/*********************************/
/* construct core-shell linkages */
/*********************************/
#define DEBUG_SHELLS 0
#define MAX_SHELL_DIST 0.6
void shell_make_links(struct model_pak *model)
{
gint match;
gdouble min, sep, vec[3];
gpointer zone;
GSList *list1, *list2, *locality, *floating;
struct core_pak *core;
struct shel_pak *shel;
/* checks */
g_assert(model != NULL);
g_assert(model->zone_array != NULL);
/* enumerate all shells */
floating = NULL;
for (list1=model->shels ; list1 ; list1=g_slist_next(list1))
{
shel = list1->data;
/* get neighbourhood core list for the shell */
zone = zone_get(shel->x, model->zone_array);
locality = zone_area_cores(1, zone, model->zone_array);
/* upper bound for core-shell link */
min = MAX_SHELL_DIST*MAX_SHELL_DIST;
/* enumerate cores in the shell's vicinity */
match = 0;
for (list2=locality ; list2 ; list2=g_slist_next(list2))
{
core = list2->data;
if (shel->atom_code == core->atom_code)
{
/* get the minimum fractional separation */
ARR3SET(vec, core->x);
ARR3SUB(vec, shel->x);
fractional_minsq(vec, model->periodic);
/* convert to cartesian & compare with cutoff */
vecmat(model->latmat, vec);
sep = VEC3MAGSQ(vec);
if (sep < min)
{
/* FIXME - what to do with previous matches? eg set (core->shell)->shell = NULL ? */
/* reference each other */
core->shell = shel;
shel->core = core;
match++;
/* keep track of the minimum, so only the closest pair is recorded */
min = sep;
}
}
}
/* record any shells with no linkages */
if (!match)
{
floating = g_slist_prepend(floating, shel);
error_table_entry("Error: found shell with no core.\n");
}
/* free the constructed locality */
g_slist_free(locality);
}
/* found some floating shells? */
if (floating)
{
/*
text = g_strdup_printf("Warning: found %d shell(s) with no core(s).\n",
g_slist_length(floating));
gui_text_show(WARNING, text);
g_free(text);
*/
/* flag shells (diff colour?) with no cores */
for (list1=floating ; list1 ; list1=g_slist_next(list1))
{
shel = list1->data;
/*
printf("Floating shell=%p\n", shel);
*/
VEC3SET(shel->colour, 1.0, 1.0, 1.0);
}
g_slist_free(floating);
}
}
/*********************************/
/* coordinate matching routine 1 */
/*********************************/
/* done via 3D world coordinate matching */
#define DEBUG_SEEK_COORD3D 0
struct core_pak *seek_coord3d(gdouble *x, struct model_pak *data)
{
gdouble d2, tol, vec[3], piv[3];
GSList *list=NULL, *ilist=NULL;
struct core_pak *core, *best=NULL;
struct image_pak *image;
/* tolerance (angstroms squared) */
tol = data->rmax * 20.0/sysenv.size;
#if DEBUG_SEEK_COORD3D
printf(" size = %d\n", sysenv.size);
printf(" rmax = %f\n", data->rmax);
printf(" tol = %f\n", tol);
#endif
do
{
if (ilist)
{
/* retrieve periodic image vector */
image = ilist->data;
ARR3SET(piv, image->rx);
ilist = g_slist_next(ilist);
}
else
{
VEC3SET(piv, 0.0, 0.0, 0.0);
ilist = data->images;
}
/* attempt to match core coords */
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
ARR3SET(vec, core->rx);
ARR3ADD(vec, piv);
ARR3SUB(vec, x);
d2 = vec[0]*vec[0] + vec[1]*vec[1];
if (d2 < tol)
{
best = core;
tol = d2;
}
}
}
while (ilist);
return(best);
}
/*********************************/
/* coordinate matching routine 2 */
/*********************************/
/* done via 2D window coordinate matching */
#define DEBUG_SEEK_COORD2D 0
struct core_pak *seek_coord2d(gint x, gint y, struct model_pak *data)
{
gint tol, d2, w[2];
gdouble vec[3];
GSList *list=NULL;
struct core_pak *core, *best=NULL;
/* tolerance (pixels squared) */
tol = 49;
#if DEBUG_SEEK_COORD2D
printf("search: [%d,%d]\n", x, y);
#endif
/* TODO - periodic images */
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
ARR3SET(vec, core->rx);
gl_unproject(w, vec, canvas_find(data));
#if DEBUG_SEEK_COORD2D
printf(" (%d, %d)\n", w[0], w[1]);
#endif
w[0] -= x;
w[1] -= y;
d2 = w[0]*w[0] + w[1]*w[1];
if (d2 < tol)
{
best = core;
tol = d2;
}
}
return(best);
}
/******************************/
/* vertex coordinate extremes */
/******************************/
void vertex_limits(gdouble *min, gdouble *max, struct model_pak *model)
{
gint i;
gdouble x[3];
GSList *list;
struct vertex_pak *v;
g_assert(model != NULL);
/* failsafe limit init */
VEC3SET(min, 0.0, 0.0, 0.0);
VEC3SET(max, 0.0, 0.0, 0.0);
list = model->vertices;
if (!list)
return;
/* failsafe limit init */
v = list->data;
ARR3SET(x, v->x);
ARR3SET(min, x);
ARR3SET(max, x);
/* scan list and update limits */
while (list)
{
v = list->data;
ARR3SET(x, v->x);
for (i=3 ; i-- ; )
{
if (x[i] < min[i])
min[i] = x[i];
if (x[i] > max[i])
max[i] = x[i];
}
list = g_slist_next(list);
}
}
/**********/
/* COORDS */
/**********/
#define DEBUG_CENT 0
gint coords_center(gint global, struct model_pak *data)
{
gint i, n;
gdouble min[3], max[3], vec[3], r, r2, rmax;
GSList *list=NULL, *ilist, *clist;
struct image_pak *image;
struct spatial_pak *spatial;
struct core_pak *core;
struct vertex_pak *v;
struct vec_pak *p1;
/* initialize */
VEC3SET(data->offset, 0, 0, 0);
VEC3SET(data->centroid, 0.0, 0.0, 0.0);
r2 = 0.0;
/* core list is (non-empty) selection for non global scaling */
clist = data->cores;
if (!global && g_slist_length(data->selection))
clist = data->selection;
/* centroid calc */
n=0;
for (list=clist ; list ; list=g_slist_next(list))
{
core = list->data;
if (core->status & DELETED)
continue;
ARR3ADD(data->centroid, core->x);
n++;
}
if (n)
{
VEC3MUL(data->centroid, 1.0 / (gdouble) n);
}
else
{
/* if we have no atoms in a periodic model - make pbc/2 the centroid */
if (data->periodic)
{
VEC3SET(data->centroid, 0.5, 0.5, 0.5);
}
else
{
/* morphology centroid (NB: won't be the origin if non-centrosymetric) */
vertex_limits(min, max, data);
ARR3SET(data->centroid, min);
ARR3ADD(data->centroid, max);
VEC3MUL(data->centroid, 0.5);
}
}
/* NEW - always make a pbc/2 the centroid */
for (i=data->periodic ; i-- ; )
data->centroid[i] = 0.5;
/* adjust for periodic images */
n=1;
VEC3SET(vec, 0.0, 0.0, 0.0);
for (list=data->images ; list ; list=g_slist_next(list))
{
image = list->data;
ARR3ADD(vec, image->pic);
n++;
}
VEC3MUL(vec, 1.0 / (gdouble) n);
ARR3ADD(data->centroid, vec);
/* get distance of furtherest displayed item from centroid */
for (list=clist ; list ; list=g_slist_next(list))
{
core = list->data;
if (core->status & DELETED)
continue;
ilist=NULL;
do
{
ARR3SET(vec, core->x);
if (ilist)
{
image = ilist->data;
/* image */
ARR3ADD(vec, image->pic);
ilist = g_slist_next(ilist);
}
else
{
ilist = data->images;
}
ARR3SUB(vec, data->centroid);
vecmat(data->latmat,vec);
/* dist squared */
r = VEC3MAGSQ(vec);
if (r > r2)
r2 = r;
}
while (ilist);
}
/* check cell vertices */
if (data->periodic)
{
for (i=8 ; i-- ; )
{
ARR3SET(vec, data->cell[i].x);
/* centroid removal */
ARR3SUB(vec, data->centroid);
/* transform */
vecmat(data->latmat, vec);
/* dist sq. */
r = VEC3MAGSQ(vec);
if (r > r2)
r2 = r;
}
}
/* check morphology vertices */
for (list=data->vertices ; list ; list=g_slist_next(list))
{
v = list->data;
ARR3SET(vec, v->x);
ARR3SUB(vec, data->centroid);
vecmat(data->latmat, vec);
r = VEC3MAGSQ(vec);
if (r > r2)
r2 = r;
}
/* check spatial objects */
for (list=data->spatial ; list ; list=g_slist_next(list))
{
spatial = list->data;
p1 = g_slist_nth_data(spatial->list, 0);
if (p1)
{
ARR3SET(vec, p1->x);
ARR3SUB(vec, data->centroid);
vecmat(data->latmat, vec);
r = VEC3MAGSQ(vec);
if (r > r2)
r2 = r;
}
}
/* check camera waypoints */
for (list=data->waypoint_list ; list ; list=g_slist_next(list))
{
struct camera_pak *camera = list->data;
r = VEC3MAGSQ(camera->x);
if (r > r2)
r2 = r;
}
/* assign the calculated value, unless 0 */
rmax = sqrt(r2);
if (rmax)
data->rmax = rmax;
else
data->rmax = 5.0; /* seems to give ~ correct axes lengths */
data->zoom = data->rmax;
#if DEBUG_CENT
P3VEC("centroid = ", data->centroid);
printf("rmax = %f\n", data->rmax);
printf("zoom = %f\n", data->zoom);
printf("coords_center() done.\n");
P3MAT("latmat", data->latmat);
#endif
return(0);
}
/******************************************/
/* sort coords by z - mainly for surfaces */
/******************************************/
gint sort_cores(struct core_pak *core1, struct core_pak *core2)
{
if (core1->x[2] < core2->x[2])
return(1);
if (core1->x[2] > core2->x[2])
return(-1);
return(0);
}
gint sort_shels(struct shel_pak *shel1, struct shel_pak *shel2)
{
if (shel1->x[2] < shel2->x[2])
return(1);
if (shel1->x[2] > shel2->x[2])
return(-1);
return(0);
}
void sort_coords(struct model_pak *data)
{
data->cores = g_slist_sort(data->cores, (gpointer) sort_cores);
data->shels = g_slist_sort(data->shels, (gpointer) sort_shels);
}
/*************************/
/* get coordinate limits */
/*************************/
void cor_calc_xlimits(gdouble *min, gdouble *max, GSList *list)
{
gint i;
GSList *item;
struct core_pak *core;
/* no cores? */
if (!list)
return;
/* init */
core = list->data;
for (i=3 ; i-- ; )
min[i] = max[i] = core->x[i];
/* NB: even tho' we check the "fractional" part - the values */
/* will still be cartesian for isolated (or the appropriate */
/* mixed frac/cart values for 1D/2D) models */
/* FIXME - not always true - newly generated surfaces have z values */
/* in fractional coords */
/* loop to get limits */
for (item=list ; item ; item=g_slist_next(item))
{
core = item->data;
for (i=3 ; i-- ; )
{
if (core->x[i] < min[i])
min[i] = core->x[i];
if (core->x[i] > max[i])
max[i] = core->x[i];
}
}
}
/**********************************/
/* compute cartesian world coords */
/**********************************/
/* TODO - make more fine grained ie cores/shells or spatials (or ALL) */
#define DEBUG_UPDATE_COORDS 0
void coords_compute(struct model_pak *data)
{
gint n, ghost, model;
gdouble vec[3];
gdouble mat4[16], vec4[4];
GSList *list=NULL, *list1, *list2;
struct core_pak *core;
struct shel_pak *shell;
struct model_pak *orig;
struct vec_pak *vector;
struct vertex_pak *v;
struct plane_pak *plane;
struct ribbon_pak *ribbon;
struct spatial_pak *spatial;
struct object_pak *odata;
struct image_pak *image;
GSList *plist, *glist=NULL, *olist;
#if DEBUG_UPDATE_COORDS
printf("coords_compute() start.\n");
#endif
g_return_if_fail(data != NULL);
/* update model & any overlayed (ghost) models */
ghost=0;
orig = data;
while(data)
{
#if DEBUG_UPDATE_COORDS
P3MAT("instantaneous rot matrix", rot);
P3MAT("cummulative rot matrix", data->rotmat);
P3MAT(" irot matrix", data->irotmat);
#endif
/* precalc matrix products */
ARR3SET(&mat4[0], &data->latmat[0]);
ARR3SET(&mat4[4], &data->latmat[3]);
ARR3SET(&mat4[8], &data->latmat[6]);
ARR3SET(vec, data->centroid);
vecmat(data->latmat, vec);
mat4[3] = -vec[0];
mat4[7] = -vec[1];
mat4[11] = -vec[2];
VEC4SET(&mat4[12], 0.0, 0.0, 0.0, 1.0);
#if DEBUG_UPDATE_COORDS
P4MAT("mat4:", mat4);
#endif
memcpy(data->display_lattice, mat4, 16*sizeof(gdouble));
/* update image translation vectors */
for (list=data->images ; list ; list=g_slist_next(list))
{
image = list->data;
ARR3SET(vec4, image->pic);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
ARR3SET(image->rx, vec4);
}
/* calculate for atoms */
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
if (core->status & DELETED)
continue;
ARR3SET(vec4, core->x);
ARR3ADD(vec4, core->offset);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(core->rx, vec4);
}
/* calculate for shells */
for (list=data->shels ; list ; list=g_slist_next(list))
{
shell = list->data;
if (shell->status & DELETED)
continue;
ARR3SET(vec4, shell->x);
ARR3ADD(vec4, shell->offset);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(shell->rx, vec4);
}
/* cell */
for (n=8 ; n-- ; )
{
ARR3SET(vec4, data->cell[n].x);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(data->cell[n].rx, vec4);
}
/* axes */
for (n=6 ; n-- ; )
{
ARR3SET(vec4, data->axes[n].x);
vec4[3] = 0.0;
if (data->axes_type != CARTESIAN)
{
vec4mat(mat4, vec4);
normalize(vec4, 3);
}
ARR3SET(data->axes[n].rx, vec4);
VEC3MUL(data->axes[n].rx, 0.06*data->rmax);
}
/* ribbon updates */
olist = data->ribbons;
while (olist)
{
odata = olist->data;
switch (odata->type)
{
case RIBBON:
plist = (GSList *) odata->data;
while (plist != NULL)
{
ribbon = plist->data;
/* end point 1 */
ARR3SET(vec4, ribbon->x1);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->r1, vec4);
/* end point 2 */
ARR3SET(vec4, ribbon->x2);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->r2, vec4);
/* normal 1 */
ARR3SET(vec4, ribbon->u1);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->n1, vec4);
/* normal 2 */
ARR3SET(vec4, ribbon->u2);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->n2, vec4);
/* orientation vector 1 */
ARR3SET(vec4, ribbon->v1);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->o1, vec4);
/* orientation vector 2 */
ARR3SET(vec4, ribbon->v2);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
ARR3SET(ribbon->o2, vec4);
plist = g_slist_next(plist);
}
break;
}
olist = g_slist_next(olist);
}
/* spatials */
for (olist=data->spatial ; olist ; olist=g_slist_next(olist))
{
spatial = olist->data;
plist = spatial->list;
while (plist)
{
vector = plist->data;
/* rotate each point */
ARR3SET(vec4, vector->x);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(vector->rx, vec4);
/* rotate the normal */
ARR3SET(vec4, vector->n);
vec4[3] = 0.0;
vec4mat(mat4, vec4);
normalize(vec4, 3);
ARR3SET(vector->rn, vec4);
plist = g_slist_next(plist);
}
}
/* morphology */
for (list1=data->vertices ; list1 ; list1=g_slist_next(list1))
{
v = list1->data;
ARR3SET(vec4, v->x);
vec4[3] = 1.0;
vec4mat(mat4, vec4);
ARR3SET(v->rx, vec4);
}
/* compute facet center (miller label placement) */
for (list1=data->planes ; list1 ; list1=g_slist_next(list1))
{
plane = list1->data;
if (plane->present)
{
VEC3SET(vec, 0.0, 0.0, 0.0);
n = 0;
for (list2=plane->vertices ; list2 ; list2=g_slist_next(list2))
{
v = list2->data;
ARR3ADD(vec, v->rx);
n++;
}
/* assign */
/* NB: n=0 can sometimes occur with a bad (ie non-closed) polyhedron */
if (n)
{
VEC3MUL(vec, 1.0/(gdouble) n);
}
ARR3SET(plane->rx, vec);
}
}
/* ghost processsing */
if (!ghost)
{
glist = data->ghosts;
ghost++;
}
else
glist = g_slist_next(glist);
/* get the ghost model's pointer */
if (glist)
{
model = GPOINTER_TO_INT(glist->data);
data = model_ptr(model, RECALL);
}
else
data = NULL;
}
#if DEBUG_UPDATE_COORDS
printf("coords_compute() done.\n");
#endif
}
/***********************************/
/* print atom coord data primitive */
/***********************************/
void print_core(struct core_pak *core)
{
gchar *txt;
g_assert(core != NULL);
txt = g_strdup_printf("%4s core at (%9.4f,%9.4f,%9.4f).\n",
core->atom_label, core->x[0], core->x[1], core->x[2]);
gui_text_show(STANDARD, txt);
g_free(txt);
}
/***********************************/
/* print atom coord data primitive */
/***********************************/
void print_core_cart(struct core_pak *core)
{
gchar *txt;
g_assert(core != NULL);
txt = g_strdup_printf("%4s core at (%9.4f,%9.4f,%9.4f).\n",
core->atom_label, core->rx[0], core->rx[1], core->rx[2]);
gui_text_show(STANDARD, txt);
g_free(txt);
}
/************************************/
/* print shell coord data primitive */
/************************************/
void print_shell(struct shel_pak *shell)
{
gchar *txt;
g_assert(shell != NULL);
txt = g_strdup_printf("%4s shel at (%9.4f,%9.4f,%9.4f) [%9.4f, %9.4f, %9.4f]\n",
shell->shell_label, shell->x[0], shell->x[1], shell->x[2],
shell->rx[0], shell->rx[1], shell->rx[2]);
gui_text_show(STANDARD, txt);
g_free(txt);
}
void print_cores(struct model_pak *data)
{
GSList *list;
struct core_pak *core;
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
printf("%4s core at (%9.4f,%9.4f,%9.4f).\n",
core->atom_label, core->x[0], core->x[1], core->x[2]);
}
}
void print_cores_cart(struct model_pak *data)
{
GSList *list;
struct core_pak *core;
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
printf("%4s core at (%9.4f,%9.4f,%9.4f).\n",
core->atom_label, core->rx[0], core->rx[1], core->rx[2]);
}
}
void print_shells(struct model_pak *data)
{
GSList *list;
struct shel_pak *shel;
for (list=data->shels ; list ; list=g_slist_next(list))
{
shel = list->data;
printf("%4s shel at (%9.4f,%9.4f,%9.4f).\n",
shel->shell_label, shel->x[0], shel->x[1], shel->x[2]);
}
}
/****************************************/
/* print all connected cores and shells */
/****************************************/
void print_core_shell(struct model_pak *data)
{
gint n=0;
GSList *list;
struct core_pak *core;
struct shel_pak *shel;
for (list=data->cores ; list ; list=g_slist_next(list))
{
core = list->data;
if (core->shell)
{
shel = core->shell;
if (n == 7 || n == 15)
{
printf("(%p) %4s core at (%9.4f,%9.4f,%9.4f).\n",
core, core->atom_label, core->x[0], core->x[1], core->x[2]);
printf("(%p) %4s shel at (%9.4f,%9.4f,%9.4f).\n",
shel, shel->shell_label, shel->x[0], shel->x[1], shel->x[2]);
}
n++;
}
}
}
/***********************/
/* core free primitive */
/***********************/
void core_free(gpointer data)
{
struct core_pak *core = data;
g_free(core->atom_label);
g_free(core->atom_type);
g_free(core->res_name);
g_free(core->flags);
g_free(core->chain);
g_slist_free(core->bonds);
free_slist(core->vibx_list);
free_slist(core->viby_list);
free_slist(core->vibz_list);
g_free(core);
}
/****************************************************/
/* free all lists that reference cores or core data */
/****************************************************/
void free_core_list(struct model_pak *data)
{
GSList *list;
g_assert(data != NULL);
/* free all objects that contain core refs first */
/* free shells */
/* TODO - free shell data */
free_slist(data->shels);
data->shels = NULL;
/* free connectivity */
free_slist(data->bonds);
data->bonds = NULL;
free_slist(data->ubonds);
data->ubonds = NULL;
free_mol_list(data);
data->moles = NULL;
/* others */
g_slist_free(data->selection);
data->selection = NULL;
/* NB: don't free data */
g_slist_free(data->unique_atom_list);
data->unique_atom_list = NULL;
/* free the cores */
for (list=data->cores ; list ; list=g_slist_next(list))
core_free(list->data);
g_slist_free(data->cores);
data->cores = NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1