1 /* Copyright (C) 2000-2002 Damir Zucic */
2 
3 /*=============================================================================
4 
5 				rotate.c
6 
7 Purpose:
8 	Rotate all caught macromolecular complexes  or edit default complex.
9 
10 Input:
11 	(1) Pointer to MolComplexS structure, with macromolecular complexes.
12 	(2) Number of macromolecular complexes.
13 	(3) Pointer to RuntimeS structure.
14 	(4) Pointer to ConfigS structure.
15 	(5) Rotation angle.
16 	(6) Rotation axis identifier (1 = x, 2 = y, 3 = z).
17 
18 Output:
19 	(1) Atoms rotated in all caught macromolecular complexes.
20 
21 Return value:
22 	(1) Edit mode index (positive or zero) on success.
23 	(2) Negative on failure.
24 
25 ========includes:============================================================*/
26 
27 #include <stdio.h>
28 
29 #include <math.h>
30 
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33 #include <X11/Xos.h>
34 #include <X11/Xatom.h>
35 
36 #include "defines.h"
37 #include "typedefs.h"
38 
39 /*======function prototypes:=================================================*/
40 
41 int		EditPhi_ (MolComplexS *, RuntimeS *, ConfigS *, double);
42 int		EditPsi_ (MolComplexS *, RuntimeS *, ConfigS *, double);
43 int		EditOmega_ (MolComplexS *, RuntimeS *, ConfigS *, double);
44 int		EditBond_ (MolComplexS *, int, RuntimeS *, ConfigS *, double);
45 int		EditChi1_ (MolComplexS *, RuntimeS *, ConfigS *, double);
46 int		EditChi2_ (MolComplexS *, RuntimeS *, ConfigS *, double);
47 int		PrepareStereoData_ (MolComplexS *, ConfigS *);
48 void		RotatePlane_ (MolComplexS *, ConfigS *, double, int);
49 void		RotateMembrane_ (MolComplexS *, ConfigS *, double, int);
50 
51 /*======rotate all caught macromol. complexes:===============================*/
52 
Rotate_(MolComplexS * mol_complexSP,int mol_complexesN,RuntimeS * runtimeSP,ConfigS * configSP,double rotation_angle,int axisID)53 int Rotate_ (MolComplexS *mol_complexSP, int mol_complexesN,
54 	      RuntimeS *runtimeSP, ConfigS *configSP,
55 	      double rotation_angle, int axisID)
56 {
57 MolComplexS	*curr_mol_complexSP;
58 int		edit_modeI;
59 int		mol_complexI;
60 double		cos_angle, sin_angle;
61 size_t		atomsN, atomI;
62 AtomS		*curr_atomSP;
63 double		x0, y0, z0, x, y, z, x_new = 0.0, y_new = 0.0, z_new = 0.0;
64 
65 /* Pointer to default macromolecular complex: */
66 curr_mol_complexSP = mol_complexSP + runtimeSP->default_complexI;
67 
68 /* Copy the edit mode index: */
69 edit_modeI = runtimeSP->edit_modeI;
70 
71 /* Check the axis identifier and edit mode index. */
72 
73 /* If axisID is three and edit_modeI is two, three, four or */
74 /* six,  edit phi, psi,  omega or selected side chain bond: */
75 if ((axisID == 3) &&
76     ((edit_modeI == 2) || (edit_modeI == 3) ||
77      (edit_modeI == 4) || (edit_modeI == 6)))
78 	{
79 	/* Edit phi: */
80 	if (edit_modeI == 2)
81 		{
82 		EditPhi_ (curr_mol_complexSP,
83 			  runtimeSP, configSP,
84 			  rotation_angle);
85 		}
86 
87 	/* Edit psi: */
88 	else if (edit_modeI == 3)
89 		{
90 		EditPsi_ (curr_mol_complexSP,
91 			  runtimeSP, configSP,
92 			  rotation_angle);
93 		}
94 
95 	/* Edit omega: */
96 	else if (edit_modeI == 4)
97 		{
98 		EditOmega_ (curr_mol_complexSP,
99 			    runtimeSP, configSP,
100 			    rotation_angle);
101 		}
102 
103 	/* Edit some other bond (side chain): */
104 	else if (edit_modeI == 6)
105 		{
106 		EditBond_ (curr_mol_complexSP,
107 			   runtimeSP->default_complexI,
108 			   runtimeSP, configSP,
109 			   rotation_angle);
110 		}
111 
112 	/* Prepare the stereo data,  update one */
113 	/* flag and return the edit mode index: */
114 	/* Prepare stereo data, if required: */
115 	if (configSP->stereoF)
116 		{
117 		PrepareStereoData_ (curr_mol_complexSP, configSP);
118 		}
119 
120 	/* Set the position_changedF: */
121 	curr_mol_complexSP->position_changedF = 1;
122 
123 	/* Return the edit mode index: */
124 	return edit_modeI;
125 	}
126 
127 /* If axis identifier is two and edit_modeI is five, edit phi: */
128 else if ((axisID == 2) && (edit_modeI == 5))
129 	{
130 	/* Edit phi: */
131 	rotation_angle *= -1;
132 	EditPhi_ (curr_mol_complexSP, runtimeSP, configSP, rotation_angle);
133 
134 	/* Prepare the stereo data,  update one */
135 	/* flag and return the edit mode index: */
136 	/* Prepare stereo data, if required: */
137 	if (configSP->stereoF)
138 		{
139 		PrepareStereoData_ (curr_mol_complexSP, configSP);
140 		}
141 
142 	/* Set the position_changedF: */
143 	curr_mol_complexSP->position_changedF = 1;
144 
145 	/* Return the edit mode index: */
146 	return edit_modeI;
147 	}
148 
149 /* If axis identifier is two and edit_modeI is seven, edit chi1: */
150 else if ((axisID == 2) && (edit_modeI == 7))
151 	{
152 	/* Edit chi1: */
153 	rotation_angle *= -1;
154 	EditChi1_ (curr_mol_complexSP, runtimeSP, configSP, rotation_angle);
155 
156 	/* Prepare the stereo data,  update one */
157 	/* flag and return the edit mode index: */
158 	/* Prepare stereo data, if required: */
159 	if (configSP->stereoF)
160 		{
161 		PrepareStereoData_ (curr_mol_complexSP, configSP);
162 		}
163 
164 	/* Set the position_changedF: */
165 	curr_mol_complexSP->position_changedF = 1;
166 
167 	/* Return the edit mode index: */
168 	return edit_modeI;
169 	}
170 
171 /* If axis identifier is one and edit_modeI is five, edit psi: */
172 else if ((axisID == 1) && (edit_modeI == 5))
173 	{
174 	/* Edit psi: */
175 	rotation_angle *= -1;
176 	EditPsi_ (curr_mol_complexSP, runtimeSP, configSP, rotation_angle);
177 
178 	/* Prepare the stereo data,  update one */
179 	/* flag and return the edit mode index: */
180 	/* Prepare stereo data, if required: */
181 	if (configSP->stereoF)
182 		{
183 		PrepareStereoData_ (curr_mol_complexSP, configSP);
184 		}
185 
186 	/* Set the position_changedF: */
187 	curr_mol_complexSP->position_changedF = 1;
188 
189 	/* Return the edit mode index: */
190 	return edit_modeI;
191 	}
192 
193 /* If axis identifier is one and edit_modeI is seven, edit chi2: */
194 else if ((axisID == 1) && (edit_modeI == 7))
195 	{
196 	/* Edit chi2: */
197 	rotation_angle *= -1;
198 	EditChi2_ (curr_mol_complexSP, runtimeSP, configSP, rotation_angle);
199 
200 	/* Prepare the stereo data,  update one */
201 	/* flag and return the edit mode index: */
202 	/* Prepare stereo data, if required: */
203 	if (configSP->stereoF)
204 		{
205 		PrepareStereoData_ (curr_mol_complexSP, configSP);
206 		}
207 
208 	/* Set the position_changedF: */
209 	curr_mol_complexSP->position_changedF = 1;
210 
211 	/* Return the edit mode index: */
212 	return edit_modeI;
213 	}
214 
215 /* If this point is reached, the entire structure should be rotated. */
216 
217 /* Calculate cosine and sine of the rotation angle: */
218 cos_angle = cos (rotation_angle);
219 sin_angle = sin (rotation_angle);
220 
221 /* If working in default mode, rotate the entire structure: */
222 for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
223 	{
224 	/* Pointer to the current macromolecular complex: */
225 	curr_mol_complexSP = mol_complexSP + mol_complexI;
226 
227 	/* Check is the current macromolecular complex caught: */
228 	if (curr_mol_complexSP->catchF == 0) continue;
229 
230 	/* Check is it necessary to rotate the plane: */
231 	if (curr_mol_complexSP->move_bits & PLANE_MASK)
232 		{
233 		RotatePlane_ (curr_mol_complexSP, configSP,
234 			      rotation_angle, axisID);
235 		}
236 
237 	/* Check is it necessary to rotate the membrane: */
238 	if (curr_mol_complexSP->move_bits & MEMBRANE_MASK)
239 		{
240 		RotateMembrane_ (curr_mol_complexSP, configSP,
241 				 rotation_angle, axisID);
242 		}
243 
244 	/* Check is it necessary to rotate the structure at all: */
245 	if (!(curr_mol_complexSP->move_bits & STRUCTURE_MASK)) continue;
246 
247 	/* Copy the rotation center coordinates: */
248 	x0 = curr_mol_complexSP->rotation_center_vectorS.x;
249 	y0 = curr_mol_complexSP->rotation_center_vectorS.y;
250 	z0 = curr_mol_complexSP->rotation_center_vectorS.z;
251 
252 	/* Number of atoms in a macromolecular complex: */
253 	atomsN = curr_mol_complexSP->atomsN;
254 
255 	/* Scan all atoms in the current complex: */
256 	for (atomI = 0; atomI < atomsN; atomI++)
257 		{
258 		/* Pointer to the current atom: */
259 		curr_atomSP = curr_mol_complexSP->atomSP + atomI;
260 
261 		/* Coordinates relative to the rotation center: */
262 		x = curr_atomSP->raw_atomS.x[0] - x0;
263 		y = curr_atomSP->raw_atomS.y    - y0;
264 		z = curr_atomSP->raw_atomS.z[0] - z0;
265 
266 		/* Rotate these coordinates: */
267 		switch (axisID)
268 			{
269 			/* Rotate around x: */
270 			case 1:
271 				x_new =  x;
272 				y_new =  y * cos_angle - z * sin_angle;
273 				z_new =  y * sin_angle + z * cos_angle;
274 				break;
275 
276 			/* Rotate around y: */
277 			case 2:
278 				x_new =  x * cos_angle + z * sin_angle;
279 				y_new =  y;
280 				z_new = -x * sin_angle + z * cos_angle;
281 				break;
282 
283 			/* Rotate around z: */
284 			case 3:
285 				x_new =  x * cos_angle - y * sin_angle;
286 				y_new =  x * sin_angle + y * cos_angle;
287 				z_new =  z;
288 				break;
289 
290 			/* The impossible case: */
291 			default:
292 				;
293 				break;
294 
295 			}
296 
297 		/* Translate and store new coordinates: */
298 		curr_atomSP->raw_atomS.x[0] = x_new + x0;
299 		curr_atomSP->raw_atomS.y    = y_new + y0;
300 		curr_atomSP->raw_atomS.z[0] = z_new + z0;
301 		}
302 
303 	/* Prepare stereo data, if required: */
304 	if (configSP->stereoF)
305 		{
306 		PrepareStereoData_ (curr_mol_complexSP, configSP);
307 		}
308 
309 	/* Set the position_changedF: */
310 	curr_mol_complexSP->position_changedF = 1;
311 	}
312 
313 /* Return edit mode index: */
314 return edit_modeI;
315 }
316 
317 /*===========================================================================*/
318 
319 
320