File: rotate_atom.c

package info (click to toggle)
garlic 1.6-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,516 kB
  • sloc: ansic: 52,465; makefile: 2,254
file content (132 lines) | stat: -rw-r--r-- 4,662 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright (C) 2001 Damir Zucic */

/*=============================================================================

				rotate_atom.c

Purpose:
	Rotate the given atom about the given axis. The axis is defined
	by two points (vectors). The vector from the first point to the
	second  point  defines  the axis  direction.  The  right-handed
	rotation  is positive and the left-handed rotation is negative.

Input:
	(1) Pointer to AtomS structure.
	(2) Pointer to VectorS structure (the first point).
	(3) Pointer to VectorS structure (the second point).
	(4) The rotation angle.

Output:
	(1) Atom position changed.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

========includes:============================================================*/

#include <stdio.h>

#include <math.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/
 
double		AbsoluteValue_ (VectorS *);
int		ParallelPart_ (VectorS *, VectorS *, VectorS *);
void		VectorProduct_ (VectorS *, VectorS *, VectorS *);
double		ScalarProduct_ (VectorS *, VectorS *);

/*======rotate atom about given axis:========================================*/

int RotateAtom_ (AtomS *atomSP,
		 VectorS *vector1SP, VectorS *vector2SP, double angle)
{
VectorS		rot_axis_vectorS;
double		abs_value;
VectorS		radius_vectorS;
VectorS		parallel_vectorS;
VectorS		perpendicular_vectorS;
double		perpendicular_part;
double		reciprocal_abs_value;
VectorS		unit_vector1S, unit_vector2S;
double		cos_angle, sin_angle;
double		p1_new, p2_new;

/* Prepare the vector which defines the rotation axis: */
rot_axis_vectorS.x = vector2SP->x - vector1SP->x;
rot_axis_vectorS.y = vector2SP->y - vector1SP->y;
rot_axis_vectorS.z = vector2SP->z - vector1SP->z;

/* Check the absolute value of the rotation axis vector: */
abs_value = AbsoluteValue_ (&rot_axis_vectorS);
if (abs_value <= 0.0) return -1;

/* Prepare the radius vector of the given atom: */
radius_vectorS.x = atomSP->raw_atomS.x[0] - vector1SP->x;
radius_vectorS.y = atomSP->raw_atomS.y    - vector1SP->y;
radius_vectorS.z = atomSP->raw_atomS.z[0] - vector1SP->z;

/* Find the part of the radius vector which is parallel to the rotation */
/* axis.  Note that  we need the vector,  not just  the absolute value! */
ParallelPart_ (&parallel_vectorS, &rot_axis_vectorS, &radius_vectorS);

/* Find the part of the radius vector which */
/* is perpendicular  to the  rotation axis: */
perpendicular_vectorS.x = radius_vectorS.x - parallel_vectorS.x;
perpendicular_vectorS.y = radius_vectorS.y - parallel_vectorS.y;
perpendicular_vectorS.z = radius_vectorS.z - parallel_vectorS.z;

/* Prepare and check the absolute value of the perpendicular part: */
perpendicular_part = AbsoluteValue_ (&perpendicular_vectorS);
if (perpendicular_part <= 0.0) return -2;

/* Prepare the first unit vector, required for rotation: */
reciprocal_abs_value = 1.0 / perpendicular_part;
unit_vector1S.x = reciprocal_abs_value * perpendicular_vectorS.x;
unit_vector1S.y = reciprocal_abs_value * perpendicular_vectorS.y;
unit_vector1S.z = reciprocal_abs_value * perpendicular_vectorS.z;

/* Prepare and check the second unit vector: */
VectorProduct_ (&unit_vector2S, &rot_axis_vectorS, &unit_vector1S);
abs_value = AbsoluteValue_ (&unit_vector2S);
if (abs_value <= 0.0) return -3;
reciprocal_abs_value = 1.0 / abs_value;
unit_vector2S.x = reciprocal_abs_value * unit_vector2S.x;
unit_vector2S.y = reciprocal_abs_value * unit_vector2S.y;
unit_vector2S.z = reciprocal_abs_value * unit_vector2S.z;

/* Rotate the perpendicular vector: */
cos_angle = cos (angle);
sin_angle = sin (angle);
p1_new = perpendicular_part * cos_angle;
p2_new = perpendicular_part * sin_angle;
perpendicular_vectorS.x = p1_new * unit_vector1S.x + p2_new * unit_vector2S.x;
perpendicular_vectorS.y = p1_new * unit_vector1S.y + p2_new * unit_vector2S.y;
perpendicular_vectorS.z = p1_new * unit_vector1S.z + p2_new * unit_vector2S.z;

/* Update the radius vector: */
radius_vectorS.x = parallel_vectorS.x + perpendicular_vectorS.x;
radius_vectorS.y = parallel_vectorS.y + perpendicular_vectorS.y;
radius_vectorS.z = parallel_vectorS.z + perpendicular_vectorS.z;

/* Update the atomic coordinates: */
atomSP->raw_atomS.x[0] = radius_vectorS.x + vector1SP->x;
atomSP->raw_atomS.y    = radius_vectorS.y + vector1SP->y;
atomSP->raw_atomS.z[0] = radius_vectorS.z + vector1SP->z;

/* Return positive value (success indicator): */
return 1;
}

/*===========================================================================*/