1
/* Copyright (C) 2000 Damir Zucic */
3
/*=============================================================================
8
Draw atoms as big spheres, version 2 (spacefill style 2).
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 (sp2.c). The values used
36
=============================================================================*/
43
#include <X11/Xutil.h>
45
#include <X11/Xatom.h>
50
/*======function prototypes:=================================================*/
52
unsigned long Sp2Color_ (AtomS *, GUIS *, double);
54
/*======draw atoms as big spheres, version 2:================================*/
56
int DrawBigSpheres2_ (MolComplexS *mol_complexSP, int mol_complexesN,
57
ConfigS *configSP, GUIS *guiSP,
58
NearestAtomS *nearest_atomSP, size_t pixelsN,
59
unsigned int refreshI)
62
double scale_factor, user_atomic_position;
63
int left_edge[2], right_edge[2];
65
MolComplexS *curr_mol_complexSP;
68
int screen_x0, screen_y0;
69
double radius, radius_squared;
70
double denominator, reciprocal_denominator;
72
long screen_radius_squared;
73
int screen_x1, screen_y1, screen_x2, screen_y2;
74
int screen_x, screen_y;
75
long delta_x, delta_y, distance_squared;
76
double z0, front_z, delta_z, z;
78
NearestAtomS *curr_pixelSP;
79
double denominator2, reciprocal_denominator2;
82
double abs_value, abs_value_squared;
83
double scalar_product, cos_angle;
84
unsigned long colorID;
86
/* Number of images: */
87
if (configSP->stereoF) imagesN = 2;
90
scale_factor = configSP->user_screen_atomic_distance *
91
configSP->atomic_to_screen_scale_x;
93
/* Prepare the user position in atomic coordinates: */
94
user_atomic_position = configSP->user_atomic_position;
96
/* Left and right image edge (in stereo mode there are two images): */
97
left_edge[0] = configSP->image_screen_x0[0];
98
right_edge[0] = configSP->image_screen_x1[0];
99
left_edge[1] = configSP->image_screen_x0[1];
100
right_edge[1] = configSP->image_screen_x1[1];
102
/*------first pass - fill NearestAtomS array with planar atoms:--------------*/
104
/* Draw each macromolecular complex: */
105
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
107
/* Pointer to current macromolecular complex: */
108
curr_mol_complexSP = mol_complexSP + mol_complexI;
110
/* Prepare and check the number of atoms: */
111
atomsN = curr_mol_complexSP->atomsN;
112
if (atomsN == 0) continue;
114
/* Draw atoms which have the given style: */
115
for (atomI = 0; atomI < atomsN; atomI++)
117
/* Pointer to the current atom: */
118
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
121
if (curr_atomSP->raw_atomS.atom_styleI != BIG_SPHERE2) continue;
123
/* Check is atom hidden: */
124
if (curr_atomSP->hiddenF) continue;
126
/* Check is atom inside slab: */
127
if (!curr_atomSP->inside_slabF) continue;
129
/* Check is atom inside window: */
130
if (!curr_atomSP->inside_windowF) continue;
132
/* Atomic radius, in atomic units: */
133
radius = curr_atomSP->raw_atomS.van_der_Waals_radius;
135
/* The y coordinate of atomic center, in screen units: */
136
screen_y0 = curr_atomSP->raw_atomS.screen_y;
138
/* Prepare one image (mono) or two images (stereo): */
139
for (imageI = 0; imageI < imagesN; imageI++)
141
/* The z coordinate of atomic center, in atomic units: */
142
z0 = curr_atomSP->raw_atomS.z[imageI];
144
/* Prepare the factor required for projection of atomic radius: */
145
denominator = z0 - user_atomic_position;
146
if (denominator == 0.0) continue;
147
reciprocal_denominator = 1.0 / denominator;
149
/* Atomic radius in screen units: */
150
screen_radius = (int) (radius *
152
reciprocal_denominator +
155
/* Screen radius squared (used to improve speed): */
156
screen_radius_squared = (long) screen_radius *
157
(long) screen_radius;
159
/* The x coordinate of atomic center, in screen units: */
160
screen_x0 = curr_atomSP->raw_atomS.screen_x[imageI];
162
/* Define the bounding rectangle: */
163
screen_x1 = screen_x0 - screen_radius;
164
screen_y1 = screen_y0 - screen_radius;
165
screen_x2 = screen_x0 + screen_radius;
166
screen_y2 = screen_y0 + screen_radius;
168
/* Horizontal scan: */
169
for (screen_x = screen_x1; screen_x <= screen_x2; screen_x++)
171
/* Check horizontal position: */
172
if (screen_x < left_edge[imageI]) continue;
173
if (screen_x > right_edge[imageI]) continue;
176
for (screen_y = screen_y1; screen_y <= screen_y2; screen_y++)
178
/* Check vertical position: */
179
if (screen_y < 0) continue;
180
if (screen_y >= guiSP->main_win_free_area_height) continue;
182
/* Check distance from the circle center: */
183
delta_x = (long) (screen_x - screen_x0);
184
delta_y = (long) (screen_y - screen_y0);
185
distance_squared = delta_x * delta_x + delta_y * delta_y;
186
if (distance_squared > screen_radius_squared) continue;
188
/* Prepare index to the array */
189
/* of NearestAtomS structures: */
190
pixelI = guiSP->main_win_free_area_width * screen_y +
193
/* Check the pixel index: */
194
if (pixelI >= pixelsN) continue;
196
/* Pointer to NearestAtomS struct. */
197
/* assigned to current coordinates: */
198
curr_pixelSP = nearest_atomSP + pixelI;
200
/* Check was this pixel used already in */
201
/* this drawing step; if it was, compare */
202
/* the z value of the current atom with z */
203
/* value previously stored to this pixel: */
204
if (refreshI == curr_pixelSP->last_refreshI)
206
if (z0 > curr_pixelSP->z) continue;
209
/* Refresh the content of NearestAtomS */
210
/* array associated with this pixel: */
211
curr_pixelSP->styleI = BIG_SPHERE2;
212
curr_pixelSP->last_refreshI = refreshI;
213
curr_pixelSP->mol_complexI = mol_complexI;
214
curr_pixelSP->atomI = atomI;
215
curr_pixelSP->z = z0;
221
} /* mol_complexI loop */
223
/*------second pass - draw spherical atoms:----------------------------------*/
225
/* Draw each macromolecular complex: */
226
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
228
/* Pointer to current macromolecular complex: */
229
curr_mol_complexSP = mol_complexSP + mol_complexI;
231
/* Prepare and check the number of atoms: */
232
atomsN = curr_mol_complexSP->atomsN;
233
if (atomsN == 0) continue;
235
/* Draw atoms which have the given style: */
236
for (atomI = 0; atomI < atomsN; atomI++)
238
/* Pointer to the current atom: */
239
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
242
if (curr_atomSP->raw_atomS.atom_styleI != BIG_SPHERE2) continue;
244
/* Check is atom hidden: */
245
if (curr_atomSP->hiddenF) continue;
247
/* Check is atom inside slab: */
248
if (!curr_atomSP->inside_slabF) continue;
250
/* Check is atom inside window: */
251
if (!curr_atomSP->inside_windowF) continue;
253
/* Atomic radius, in atomic units: */
254
radius = curr_atomSP->raw_atomS.van_der_Waals_radius;
256
/* Squared atomic radius: */
257
radius_squared = radius * radius;
259
/* The y coordinate of atomic center, in screen units: */
260
screen_y0 = curr_atomSP->raw_atomS.screen_y;
262
/* Prepare one image (mono) or two images (stereo): */
263
for (imageI = 0; imageI < imagesN; imageI++)
265
/* The z coordinate of atomic center, in atomic units: */
266
z0 = curr_atomSP->raw_atomS.z[imageI];
268
/* The z coordinate of the nearest */
269
/* point of a given atom (sphere): */
270
front_z = z0 - radius;
272
/* Prepare the factor required for projection of atomic radius: */
273
denominator = z0 - user_atomic_position;
274
if (denominator == 0.0) continue;
275
reciprocal_denominator = 1.0 / denominator;
277
/* Atomic radius in screen units: */
278
screen_radius = (int) (radius *
280
reciprocal_denominator +
283
/* Square of the atomic radius (in screen units): */
284
screen_radius_squared = (long) screen_radius *
285
(long) screen_radius;
287
/* Reciprocal value will be used to improve performance: */
288
denominator2 = (double) screen_radius_squared;
289
if (denominator2 == 0.0) continue;
290
reciprocal_denominator2 = 1.0 / denominator2;
292
/* The x coordinate of atomic center, in screen units: */
293
screen_x0 = curr_atomSP->raw_atomS.screen_x[imageI];
295
/* Define the bounding rectangle: */
296
screen_x1 = screen_x0 - screen_radius;
297
screen_y1 = screen_y0 - screen_radius;
298
screen_x2 = screen_x0 + screen_radius;
299
screen_y2 = screen_y0 + screen_radius;
301
/* Horizontal scan: */
302
for (screen_x = screen_x1; screen_x <= screen_x2; screen_x++)
304
/* Check horizontal position: */
305
if (screen_x < left_edge[imageI]) continue;
306
if (screen_x > right_edge[imageI]) continue;
309
for (screen_y = screen_y1; screen_y <= screen_y2; screen_y++)
311
/* Check vertical position: */
312
if (screen_y < 0) continue;
313
if (screen_y >= guiSP->main_win_free_area_height) continue;
315
/* Check distance from the circle center: */
316
delta_x = (long) (screen_x - screen_x0);
317
delta_y = (long) (screen_y - screen_y0);
318
distance_squared = delta_x * delta_x + delta_y * delta_y;
319
if (distance_squared > screen_radius_squared) continue;
321
/* Prepare index to the array */
322
/* of NearestAtomS structures: */
323
pixelI = guiSP->main_win_free_area_width * screen_y +
326
/* Check the pixel index: */
327
if (pixelI >= pixelsN) continue;
329
/* Pointer to NearestAtomS struct. */
330
/* assigned to current coordinates: */
331
curr_pixelSP = nearest_atomSP + pixelI;
333
/* Check z value (this is just a quick check): */
334
if (refreshI == curr_pixelSP->last_refreshI)
336
if (front_z > curr_pixelSP->z) continue;
339
/* Calculate the accurate z value: */
340
rho_squared = radius_squared *
341
(double) distance_squared *
342
reciprocal_denominator2;
343
delta_z = sqrt (fabs (radius_squared - rho_squared));
346
/* Check z value (precise check): */
347
if (refreshI == curr_pixelSP->last_refreshI)
349
if (z > curr_pixelSP->z) continue;
352
/* The vector from sphere center to the current pixel: */
353
vectorS.x = (double) delta_x;
354
vectorS.y = (double) delta_y;
355
vectorS.z = -delta_z * scale_factor *
356
reciprocal_denominator;
357
abs_value_squared = vectorS.x * vectorS.x +
358
vectorS.y * vectorS.y +
359
vectorS.z * vectorS.z;
360
abs_value = sqrt (abs_value_squared);
362
/* The scalar product between this */
363
/* vector and light source vector: */
364
scalar_product = vectorS.x * configSP->light_vectorS.x +
365
vectorS.y * configSP->light_vectorS.y +
366
vectorS.z * configSP->light_vectorS.z;
368
/* Cosine of the angle between the vector to the */
369
/* current pixel and the light source unit vector: */
370
if (abs_value == 0.0) cos_angle = 0.0;
371
else cos_angle = scalar_product / abs_value;
374
colorID = Sp2Color_ (curr_atomSP, guiSP, cos_angle);
376
XSetForeground (guiSP->displaySP,
380
XDrawPoint (guiSP->displaySP,
381
guiSP->main_hidden_pixmapID,
385
/* Refresh the content of NearestAtomS */
386
/* array associated with this pixel: */
387
curr_pixelSP->styleI = BIG_SPHERE2;
388
curr_pixelSP->last_refreshI = refreshI;
389
curr_pixelSP->mol_complexI = mol_complexI;
390
curr_pixelSP->atomI = atomI;
392
curr_pixelSP->colorID = colorID;
398
} /* mol_complexI loop */
400
/*---------------------------------------------------------------------------*/
402
/* Return positive value (trivial): */
406
/*===========================================================================*/