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_ (¶llel_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;
}
/*===========================================================================*/
|