1
/* Copyright (C) 2000 Damir Zucic */
3
/*=============================================================================
8
Draw atoms as big spheres.
11
(1) Pointer to MolComplexS structure.
12
(2) Number of macromolecular complexes.
13
(3) Pointer to ConfigS structure, with configuration data.
14
(4) Pointer to GUIS structure.
15
(5) Pointer to NearestAtomS structure, with information about the
16
atom occupying the given pixel.
17
(6) The number of pixels in the main window free area.
18
(7) The refreshI, used to check the NearestAtomS associated with
22
(1) Spheres drawn to the hidden pixmap.
26
(1) Positive always (trivial).
29
(1) Indentation is exceptionally 4 spaces.
31
(2) The atomic radii used in this function are based on the radii
32
used in spacefill drawing function (spacefill.c). The values
33
used here are 50% larger.
35
=============================================================================*/
42
#include <X11/Xutil.h>
44
#include <X11/Xatom.h>
49
/*======function prototypes:=================================================*/
51
unsigned long SpacefillColor_ (AtomS *, GUIS *, double);
53
/*======draw atoms as big spheres:===========================================*/
55
int DrawBigSpheres_ (MolComplexS *mol_complexSP, int mol_complexesN,
56
ConfigS *configSP, GUIS *guiSP,
57
NearestAtomS *nearest_atomSP, size_t pixelsN,
58
unsigned int refreshI)
61
double scale_factor, user_atomic_position;
62
int left_edge[2], right_edge[2];
64
MolComplexS *curr_mol_complexSP;
67
int screen_x0, screen_y0;
68
double radius, radius_squared;
69
double denominator, reciprocal_denominator;
71
long screen_radius_squared;
72
int screen_x1, screen_y1, screen_x2, screen_y2;
73
int screen_x, screen_y;
74
long delta_x, delta_y, distance_squared;
75
double z0, front_z, delta_z, z;
77
NearestAtomS *curr_pixelSP;
78
double denominator2, reciprocal_denominator2;
81
double abs_value, abs_value_squared;
82
double scalar_product, cos_angle;
83
unsigned long colorID;
85
/* Number of images: */
86
if (configSP->stereoF) imagesN = 2;
89
scale_factor = configSP->user_screen_atomic_distance *
90
configSP->atomic_to_screen_scale_x;
92
/* Prepare the user position in atomic coordinates: */
93
user_atomic_position = configSP->user_atomic_position;
95
/* Left and right image edge (in stereo mode there are two images): */
96
left_edge[0] = configSP->image_screen_x0[0];
97
right_edge[0] = configSP->image_screen_x1[0];
98
left_edge[1] = configSP->image_screen_x0[1];
99
right_edge[1] = configSP->image_screen_x1[1];
101
/*------first pass - fill NearestAtomS array with planar atoms:--------------*/
103
/* Draw each macromolecular complex: */
104
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
106
/* Pointer to current macromolecular complex: */
107
curr_mol_complexSP = mol_complexSP + mol_complexI;
109
/* Prepare and check the number of atoms: */
110
atomsN = curr_mol_complexSP->atomsN;
111
if (atomsN == 0) continue;
113
/* Draw atoms which have the given style: */
114
for (atomI = 0; atomI < atomsN; atomI++)
116
/* Pointer to the current atom: */
117
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
120
if (curr_atomSP->raw_atomS.atom_styleI != BIG_SPHERE) continue;
122
/* Check is atom hidden: */
123
if (curr_atomSP->hiddenF) continue;
125
/* Check is atom inside slab: */
126
if (!curr_atomSP->inside_slabF) continue;
128
/* Check is atom inside window: */
129
if (!curr_atomSP->inside_windowF) continue;
131
/* Atomic radius, in atomic units: */
132
radius = curr_atomSP->raw_atomS.van_der_Waals_radius;
134
/* Squared atomic radius: */
135
radius_squared = radius * radius;
137
/* The y coordinate of atomic center, in screen units: */
138
screen_y0 = curr_atomSP->raw_atomS.screen_y;
140
/* Prepare one image (mono) or two images (stereo): */
141
for (imageI = 0; imageI < imagesN; imageI++)
143
/* The z coordinate of atomic center, in atomic units: */
144
z0 = curr_atomSP->raw_atomS.z[imageI];
146
/* Prepare the factor required for projection of atomic radius: */
147
denominator = z0 - user_atomic_position;
148
if (denominator == 0.0) continue;
149
reciprocal_denominator = 1.0 / denominator;
151
/* Atomic radius in screen units: */
152
screen_radius = (int) (radius *
154
reciprocal_denominator +
157
/* Screen radius squared (used to improve speed): */
158
screen_radius_squared = (long) screen_radius *
159
(long) screen_radius;
161
/* The x coordinate of atomic center, in screen units: */
162
screen_x0 = curr_atomSP->raw_atomS.screen_x[imageI];
164
/* Define the bounding rectangle: */
165
screen_x1 = screen_x0 - screen_radius;
166
screen_y1 = screen_y0 - screen_radius;
167
screen_x2 = screen_x0 + screen_radius;
168
screen_y2 = screen_y0 + screen_radius;
170
/* Horizontal scan: */
171
for (screen_x = screen_x1; screen_x <= screen_x2; screen_x++)
173
/* Check horizontal position: */
174
if (screen_x < left_edge[imageI]) continue;
175
if (screen_x > right_edge[imageI]) continue;
178
for (screen_y = screen_y1; screen_y <= screen_y2; screen_y++)
180
/* Check vertical position: */
181
if (screen_y < 0) continue;
182
if (screen_y >= guiSP->main_win_free_area_height) continue;
184
/* Check distance from the circle center: */
185
delta_x = (long) (screen_x - screen_x0);
186
delta_y = (long) (screen_y - screen_y0);
187
distance_squared = delta_x * delta_x + delta_y * delta_y;
188
if (distance_squared > screen_radius_squared) continue;
190
/* Prepare index to the array */
191
/* of NearestAtomS structures: */
192
pixelI = guiSP->main_win_free_area_width * screen_y +
195
/* Check the pixel index: */
196
if (pixelI >= pixelsN) continue;
198
/* Pointer to NearestAtomS struct. */
199
/* assigned to current coordinates: */
200
curr_pixelSP = nearest_atomSP + pixelI;
202
/* Check was this pixel used already in */
203
/* this drawing step; if it was, compare */
204
/* the z value of the current atom with z */
205
/* value previously stored to this pixel: */
206
if (refreshI == curr_pixelSP->last_refreshI)
208
if (z0 > curr_pixelSP->z) continue;
211
/* Refresh the content of NearestAtomS */
212
/* array associated with this pixel: */
213
curr_pixelSP->styleI = BIG_SPHERE;
214
curr_pixelSP->last_refreshI = refreshI;
215
curr_pixelSP->mol_complexI = mol_complexI;
216
curr_pixelSP->atomI = atomI;
217
curr_pixelSP->z = z0;
223
} /* mol_complexI loop */
225
/*------second pass - draw spherical atoms:----------------------------------*/
227
/* Draw each macromolecular complex: */
228
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
230
/* Pointer to current macromolecular complex: */
231
curr_mol_complexSP = mol_complexSP + mol_complexI;
233
/* Prepare and check the number of atoms: */
234
atomsN = curr_mol_complexSP->atomsN;
235
if (atomsN == 0) continue;
237
/* Draw atoms which have the given style: */
238
for (atomI = 0; atomI < atomsN; atomI++)
240
/* Pointer to the current atom: */
241
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
244
if (curr_atomSP->raw_atomS.atom_styleI != BIG_SPHERE) continue;
246
/* Check is atom hidden: */
247
if (curr_atomSP->hiddenF) continue;
249
/* Check is atom inside slab: */
250
if (!curr_atomSP->inside_slabF) continue;
252
/* Check is atom inside window: */
253
if (!curr_atomSP->inside_windowF) continue;
255
/* Atomic radius, in atomic units: */
256
radius = curr_atomSP->raw_atomS.van_der_Waals_radius;
258
/* Squared atomic radius: */
259
radius_squared = radius * radius;
261
/* The y coordinate of atomic center, in screen units: */
262
screen_y0 = curr_atomSP->raw_atomS.screen_y;
264
/* Prepare one image (mono) or two images (stereo): */
265
for (imageI = 0; imageI < imagesN; imageI++)
267
/* The z coordinate of atomic center, in atomic units: */
268
z0 = curr_atomSP->raw_atomS.z[imageI];
270
/* The z coordinate of the nearest */
271
/* point of a given atom (sphere): */
272
front_z = z0 - radius;
274
/* Prepare the factor required for projection of atomic radius: */
275
denominator = z0 - user_atomic_position;
276
if (denominator == 0.0) continue;
277
reciprocal_denominator = 1.0 / denominator;
279
/* Atomic radius in screen units: */
280
screen_radius = (int) (radius *
282
reciprocal_denominator +
285
/* Square of the atomic radius (in screen units): */
286
screen_radius_squared = (long) screen_radius *
287
(long) screen_radius;
289
/* Reciprocal value will be used to improve performance: */
290
denominator2 = (double) screen_radius_squared;
291
if (denominator2 == 0.0) continue;
292
reciprocal_denominator2 = 1.0 / denominator2;
294
/* The x coordinate of atomic center, in screen units: */
295
screen_x0 = curr_atomSP->raw_atomS.screen_x[imageI];
297
/* Define the bounding rectangle: */
298
screen_x1 = screen_x0 - screen_radius;
299
screen_y1 = screen_y0 - screen_radius;
300
screen_x2 = screen_x0 + screen_radius;
301
screen_y2 = screen_y0 + screen_radius;
303
/* Horizontal scan: */
304
for (screen_x = screen_x1; screen_x <= screen_x2; screen_x++)
306
/* Check horizontal position: */
307
if (screen_x < left_edge[imageI]) continue;
308
if (screen_x > right_edge[imageI]) continue;
311
for (screen_y = screen_y1; screen_y <= screen_y2; screen_y++)
313
/* Check vertical position: */
314
if (screen_y < 0) continue;
315
if (screen_y >= guiSP->main_win_free_area_height) continue;
317
/* Check distance from the circle center: */
318
delta_x = (long) (screen_x - screen_x0);
319
delta_y = (long) (screen_y - screen_y0);
320
distance_squared = delta_x * delta_x + delta_y * delta_y;
321
if (distance_squared > screen_radius_squared) continue;
323
/* Prepare index to the array */
324
/* of NearestAtomS structures: */
325
pixelI = guiSP->main_win_free_area_width * screen_y +
328
/* Check the pixel index: */
329
if (pixelI >= pixelsN) continue;
331
/* Pointer to NearestAtomS struct. */
332
/* assigned to current coordinates: */
333
curr_pixelSP = nearest_atomSP + pixelI;
335
/* Check z value (this is just a quick check): */
336
if (refreshI == curr_pixelSP->last_refreshI)
338
if (front_z > curr_pixelSP->z) continue;
341
/* Calculate the accurate z value: */
342
rho_squared = radius_squared *
343
(double) distance_squared *
344
reciprocal_denominator2;
345
delta_z = sqrt (fabs (radius_squared - rho_squared));
348
/* Check z value (precise check): */
349
if (refreshI == curr_pixelSP->last_refreshI)
351
if (z > curr_pixelSP->z) continue;
354
/* The vector from sphere center to the current pixel: */
355
vectorS.x = (double) delta_x;
356
vectorS.y = (double) delta_y;
357
vectorS.z = -delta_z * scale_factor *
358
reciprocal_denominator;
359
abs_value_squared = vectorS.x * vectorS.x +
360
vectorS.y * vectorS.y +
361
vectorS.z * vectorS.z;
362
abs_value = sqrt (abs_value_squared);
364
/* The scalar product between this */
365
/* vector and light source vector: */
366
scalar_product = vectorS.x * configSP->light_vectorS.x +
367
vectorS.y * configSP->light_vectorS.y +
368
vectorS.z * configSP->light_vectorS.z;
370
/* Cosine of the angle between the vector to the */
371
/* current pixel and the light source unit vector: */
372
if (abs_value == 0.0) cos_angle = 0.0;
373
else cos_angle = scalar_product / abs_value;
376
colorID = SpacefillColor_ (curr_atomSP, guiSP, cos_angle);
378
XSetForeground (guiSP->displaySP,
382
XDrawPoint (guiSP->displaySP,
383
guiSP->main_hidden_pixmapID,
387
/* Refresh the content of NearestAtomS */
388
/* array associated with this pixel: */
389
curr_pixelSP->styleI = BIG_SPHERE;
390
curr_pixelSP->last_refreshI = refreshI;
391
curr_pixelSP->mol_complexI = mol_complexI;
392
curr_pixelSP->atomI = atomI;
394
curr_pixelSP->colorID = colorID;
400
} /* mol_complexI loop */
402
/*---------------------------------------------------------------------------*/
404
/* Return positive value (trivial): */
408
/*===========================================================================*/