layer0/Vector.cpp (1,672 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* Copyright (c) Schrodinger, LLC. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* ------------------------------------------------------------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #include"os_predef.h" #include"os_std.h" #include"Base.h" #include"Vector.h" #include"Matrix.h" #define MASK_01010101 (((unsigned long)(-1))/3) #define MASK_00110011 (((unsigned long)(-1))/5) #define MASK_00001111 (((unsigned long)(-1))/17) #define MASK_11111111 (((unsigned long)(-1))/257) #define MASK_01010101010101010101010101010101 MASK_01010101 #define MASK_00110011001100110011001100110011 MASK_00110011 #define MASK_00001111000011110000111100001111 MASK_00001111 #define MASK_00000000111111110000000011111111 MASK_11111111 #define MASK_00000000000000001111111111111111 (((unsigned long)(-1))/65537) short countBits(unsigned long bits){ unsigned long n = bits; n = (n & MASK_01010101010101010101010101010101) + ((n >> 1) & MASK_01010101010101010101010101010101) ; n = (n & MASK_00110011001100110011001100110011) + ((n >> 2) & MASK_00110011001100110011001100110011) ; n = (n & MASK_00001111000011110000111100001111) + ((n >> 4) & MASK_00001111000011110000111100001111) ; n = (n & MASK_00000000111111110000000011111111) + ((n >> 8) & MASK_00000000111111110000000011111111) ; n = (n & MASK_00000000000000001111111111111111) + ((n >> 16) & MASK_00000000000000001111111111111111) ; return (n % 255); } short countBitsInt(int bits){ /* This could be improved to not splitting the bits into 4 variables in a loop which are 16 bits each */ unsigned long n = bits & 65535; short nbits = 0; n = (n & MASK_01010101) + ((n >> 1) & MASK_01010101) ; n = (n & MASK_00110011) + ((n >> 2) & MASK_00110011) ; n = (n & MASK_00001111) + ((n >> 4) & MASK_00001111) ; nbits += (n % 255); return nbits; } #ifndef R_SMALL #define R_SMALL 0.000000001 #endif #ifndef R_MED #define R_MED 0.00001 #endif #define cPI 3.14159265358979323846 /* pi */ static const float _0 = 0.0F; static const float _1 = 1.0F; static const double _d0 = 0.0; static const double _d1 = 1.0; void mix3f(const float *v1, const float *v2, const float fxn, float *v3) { float fxn_1 = 1.0F - fxn; v3[0] = v1[0] * fxn_1 + v2[0] * fxn; v3[1] = v1[1] * fxn_1 + v2[1] * fxn; v3[2] = v1[2] * fxn_1 + v2[2] * fxn; } void mix3d(const double *v1, const double *v2, const double fxn, double *v3) { double fxn_1 = 1.0F - fxn; v3[0] = v1[0] * fxn_1 + v2[0] * fxn; v3[1] = v1[1] * fxn_1 + v2[1] * fxn; v3[2] = v1[2] * fxn_1 + v2[2] * fxn; } unsigned int optimizer_workaround1u(unsigned int value) { return value; } float get_random0to1f() { return (rand() / (_1 + RAND_MAX)); } int pymol_roundf(float f) { if(f > 0.0F) return (int) (f + 0.49999F); else return (int) (f - 0.49999F); } void dump3i(const int *v, const char *prefix) { /* for debugging */ printf("%s %8i %8i %8i\n", prefix, v[0], v[1], v[2]); } void dump3f(const float *v, const char *prefix) { /* for debugging */ printf("%s %8.3f %8.3f %8.3f\n", prefix, v[0], v[1], v[2]); } void dump2f(const float *v, const char *prefix) { /* for debugging */ printf("%s %8.3f %8.3f\n", prefix, v[0], v[1]); } void dump3d(const double *v, const char *prefix) { /* for debugging */ printf("%s %8.3f %8.3f %8.3f\n", prefix, v[0], v[1], v[2]); } void dump4f(const float *v, const char *prefix) { /* for debugging */ printf("%s %8.3f %8.3f %8.3f %8.3f\n", prefix, v[0], v[1], v[2], v[3]); } void dump33f(const float *m, const char *prefix) { /* for debugging */ if(m) { printf("%s:0 %8.3f %8.3f %8.3f\n", prefix, m[0], m[1], m[2]); printf("%s:1 %8.3f %8.3f %8.3f\n", prefix, m[3], m[4], m[5]); printf("%s:2 %8.3f %8.3f %8.3f\n", prefix, m[6], m[7], m[8]); } else { printf("%s: (null matrix pointer)\n", prefix); } } void dump44f(const float *m, const char *prefix) { /* for debugging */ if(m) { if(prefix) { printf("%s:0 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[0], m[1], m[2], m[3]); printf("%s:1 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[4], m[5], m[6], m[7]); printf("%s:2 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[8], m[9], m[10], m[11]); printf("%s:3 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[12], m[13], m[14], m[15]); } else { } } else { printf("%s: (null matrix pointer)\n", prefix); } } void dump44d(const double *m, const char *prefix) { /* for debugging */ if(m) { printf("%s:0 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[0], m[1], m[2], m[3]); printf("%s:1 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[4], m[5], m[6], m[7]); printf("%s:2 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[8], m[9], m[10], m[11]); printf("%s:3 %8.3f %8.3f %8.3f %8.3f\n", prefix, m[12], m[13], m[14], m[15]); } else { printf("%s: (null matrix pointer)\n", prefix); } } void dump33d(const double *m, const char *prefix) { /* for debugging */ printf("%s:0 %8.3f %8.3f %8.3f\n", prefix, m[0], m[1], m[2]); printf("%s:1 %8.3f %8.3f %8.3f\n", prefix, m[3], m[4], m[5]); printf("%s:2 %8.3f %8.3f %8.3f\n", prefix, m[6], m[7], m[8]); } void get_divergent3f(const float *src, float *dst) { if(src[0] != _0) { *(dst++) = -*(src++); *(dst++) = *(src++) + 0.1F; *(dst++) = *(src++); } else if(src[1] != _0) { *(dst++) = *(src++) + 0.1F; *(dst++) = -*(src++); *(dst++) = *(src++); } else { *(dst++) = *(src++) + 0.1F; *(dst++) = *(src++); *(dst++) = -*(src++); } } int equal3f(const float *v1, const float *v2) { return ((fabs(v1[0] - v2[0]) < R_SMALL) && (fabs(v1[1] - v2[1]) < R_SMALL) && (fabs(v1[2] - v2[2]) < R_SMALL)); } void get_random3f(float *x) { /* this needs to be fixed as in Tinker */ x[0] = 0.5F - (rand() / (_1 + RAND_MAX)); x[1] = 0.5F - (rand() / (_1 + RAND_MAX)); x[2] = 0.5F - (rand() / (_1 + RAND_MAX)); normalize3f(x); } void get_system3f(float *x, float *y, float *z) { /* make random system */ get_random3f(x); get_divergent3f(x, y); cross_product3f(x, y, z); normalize3f(z); cross_product3f(z, x, y); normalize3f(y); normalize3f(x); } void get_system1f3f(float *x, float *y, float *z) { /* make system in direction of x */ get_divergent3f(x, y); cross_product3f(x, y, z); normalize3f(z); cross_product3f(z, x, y); normalize3f(y); normalize3f(x); } void get_system2f3f(float *x, float *y, float *z) { /* make system in direction of x */ cross_product3f(x, y, z); normalize3f(z); cross_product3f(z, x, y); normalize3f(y); normalize3f(x); } void extrapolate3f(const float *v1, const float *unit, float *result) { float lsq = lengthsq3f(v1); float dp = dot_product3f(v1, unit); if(dp != 0.0F) { float l2 = lsq / dp; scale3f(unit, l2, result); } } void scatter3f(float *v, float weight) { float r[3]; get_random3f(r); scale3f(r, weight, r); add3f(r, v, v); normalize3f(v); } void wiggle3f(float *v, const float *p, const float *s) { float q[3]; q[0] = (float) cos((p[0] + p[1] + p[2]) * s[1]); q[1] = (float) cos((p[0] - p[1] + p[2]) * s[1]); q[2] = (float) cos((p[0] + p[1] - p[2]) * s[1]); scale3f(q, s[0], q); add3f(q, v, v); normalize3f(v); } void copy3d3f(const double *v1, float *v2) { v2[0] = (float) v1[0]; v2[1] = (float) v1[1]; v2[2] = (float) v1[2]; } void copy3f3d(const float *v1, double *v2) { v2[0] = (double) v1[0]; v2[1] = (double) v1[1]; v2[2] = (double) v1[2]; } void min3f(const float *v1, const float *v2, float *v3) { (v3)[0] = ((v1)[0] < (v2)[0] ? (v1)[0] : (v2)[0]); (v3)[1] = ((v1)[1] < (v2)[1] ? (v1)[1] : (v2)[1]); (v3)[2] = ((v1)[2] < (v2)[2] ? (v1)[2] : (v2)[2]); } void max3f(const float *v1, const float *v2, float *v3) { (v3)[0] = ((v1)[0] > (v2)[0] ? (v1)[0] : (v2)[0]); (v3)[1] = ((v1)[1] > (v2)[1] ? (v1)[1] : (v2)[1]); (v3)[2] = ((v1)[2] > (v2)[2] ? (v1)[2] : (v2)[2]); } double dot_product3d(const double *v1, const double *v2) { return (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]); } void identity33f(float *m) { m[0] = _1; m[1] = _0; m[2] = _0; m[3] = _0; m[4] = _1; m[5] = _0; m[6] = _0; m[7] = _0; m[8] = _1; } void identity33d(double *m) { m[0] = _d1; m[1] = _d0; m[2] = _d0; m[3] = _d0; m[4] = _d1; m[5] = _d0; m[6] = _d0; m[7] = _d0; m[8] = _d1; } void identity44f(float *m1) { int a; for(a = 0; a < 16; a++) m1[a] = _0; for(a = 0; a < 16; a = a + 5) m1[a] = _1; } void identity44d(double *m1) { int a; for(a = 0; a < 16; a++) m1[a] = _d0; for(a = 0; a < 16; a = a + 5) m1[a] = _d1; } /* * Check a nxn matrix for identity */ bool is_identityf(int n, const float *m, float threshold) { int n_sq = n * n, stride = n + 1; for (int a = 0; a < n_sq; a++) { float e = (a % stride) ? _0 : _1; if (fabsf(m[a] - e) > threshold) return false; } return true; } /* * Check if two matrices are the same. The two matrices may have different * number of rows and columns, in that case only the overlaying upper left * (nrow x min(ncol1, ncol2)) submatrix is compared. */ bool is_allclosef(int nrow, const float *m1, int ncol1, const float *m2, int ncol2, float threshold) { int ncol = (ncol1 < ncol2) ? ncol1 : ncol2; for (int i = 0; i < nrow; i++) { for (int j = 0; j < ncol; j++) { int a1 = i * ncol1 + j, a2 = i * ncol2 + j; if (fabsf(m1[a1] - m2[a2]) > threshold) return false; } } return true; } /* * Check a nxm matrix is a diagonal matrix (non-diagonal elements are zero) */ bool is_diagonalf(int nrow, const float *m, int ncol, float threshold) { if (!ncol) ncol = nrow; for (int i = 0; i < nrow; ++i) { for (int j = 0; j < ncol; ++j) { if (i != j && fabsf(m[i * ncol + j]) > threshold) return false; } } return true; } /* * Determinant of the upper left 3x3 submatrix. */ double determinant33f(const float *m, int ncol) { int &a = ncol, b = ncol * 2; return m[0] * (m[a + 1] * (double) m[b + 2] - m[a + 2] * (double) m[b + 1]) - m[1] * (m[a + 0] * (double) m[b + 2] - m[a + 2] * (double) m[b + 0]) + m[2] * (m[a + 0] * (double) m[b + 1] - m[a + 1] * (double) m[b + 0]); } void glOrtho44f(float *m1, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal){ int a; /* this is set in column major order */ for(a = 0; a < 16; a++) m1[a] = _0; m1[0] = 2.f / (right-left); m1[5] = 2.f / (top-bottom); m1[10] = -2.f/(farVal-nearVal); m1[12] = - (right+left) / (right-left); m1[13] = - (top+bottom) / (top-bottom); m1[14] = - (farVal+nearVal) / (farVal-nearVal); m1[15] = _1; } void glFrustum44f(float *m1, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal){ int a; /* this is set in column major order */ for(a = 0; a < 16; a++) m1[a] = _0; m1[0] = 2.f * nearVal / (right-left); m1[5] = 2.f * nearVal / (top-bottom); m1[8] = (right+left) / (right-left); m1[9] = (top+bottom) / (top-bottom); m1[10] = -(farVal+nearVal) / (farVal-nearVal); m1[11] = -1.f; m1[14] = -2.f * (farVal * nearVal) / (farVal - nearVal); } void copy44f(const float *src, float *dst) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); } void copy44d(const double *src, double *dst) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); } void copy44d33f(const double *src, float *dst) { *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); src++; *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); src++; *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); src++; } void copy44f33f(const float *src, float *dst) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; } void copy44f44d(const float *src, double *dst) { *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); } void copy44d44f(const double *src, float *dst) { *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); *(dst++) = (float) *(src++); } void copy33f44d(const float *src, double *dst) { const double _0 = 0.0; *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = _0; *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = _0; *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = (double) *(src++); *(dst++) = _0; *(dst++) = _0; *(dst++) = _0; *(dst++) = _0; *(dst++) = _1; } void copy33f44f(const float *src, float *dst) { const float _0 = 0.0; *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = _0; *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = _0; *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = _0; *(dst++) = _0; *(dst++) = _0; *(dst++) = _0; *(dst++) = _1; } /* Transformation: MatMult( (3x3), (3x1) = (3x1) ) */ void transform33f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; m3[0] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2; m3[1] = m1[3] * m2r0 + m1[4] * m2r1 + m1[5] * m2r2; m3[2] = m1[6] * m2r0 + m1[7] * m2r1 + m1[8] * m2r2; } void transpose33f33f(const float *m1, float *m2) { m2[0] = m1[0]; m2[1] = m1[3]; m2[2] = m1[6]; m2[3] = m1[1]; m2[4] = m1[4]; m2[5] = m1[7]; m2[6] = m1[2]; m2[7] = m1[5]; m2[8] = m1[8]; } void transpose33d33d(const double *m1, double *m2) { m2[0] = m1[0]; m2[1] = m1[3]; m2[2] = m1[6]; m2[3] = m1[1]; m2[4] = m1[4]; m2[5] = m1[7]; m2[6] = m1[2]; m2[7] = m1[5]; m2[8] = m1[8]; } void transpose44f44f(const float *m1, float *m2) { m2[0] = m1[0]; m2[1] = m1[4]; m2[2] = m1[8]; m2[3] = m1[12]; m2[4] = m1[1]; m2[5] = m1[5]; m2[6] = m1[9]; m2[7] = m1[13]; m2[8] = m1[2]; m2[9] = m1[6]; m2[10] = m1[10]; m2[11] = m1[14]; m2[12] = m1[3]; m2[13] = m1[7]; m2[14] = m1[11]; m2[15] = m1[15]; } void transpose44d44d(const double *m1, double *m2) { m2[0] = m1[0]; m2[1] = m1[4]; m2[2] = m1[8]; m2[3] = m1[12]; m2[4] = m1[1]; m2[5] = m1[5]; m2[6] = m1[9]; m2[7] = m1[13]; m2[8] = m1[2]; m2[9] = m1[6]; m2[10] = m1[10]; m2[11] = m1[14]; m2[12] = m1[3]; m2[13] = m1[7]; m2[14] = m1[11]; m2[15] = m1[15]; } void transform33Tf3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; m3[0] = m1[0] * m2r0 + m1[3] * m2r1 + m1[6] * m2r2; m3[1] = m1[1] * m2r0 + m1[4] * m2r1 + m1[7] * m2r2; m3[2] = m1[2] * m2r0 + m1[5] * m2r1 + m1[8] * m2r2; } /* multiply the upper-left 3x3 of a 4x4, m, by m2 and put result into m3: * m3 = A x m2 */ void transform44f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; m3[0] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2 + m1[3]; m3[1] = m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2 + m1[7]; m3[2] = m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2 + m1[11]; } /* Multi the upper left 3x3 of a 4x4 by a 3x1 vector; so effectively, [3x3]*[3x1] = [3x1] */ void transform44d3f(const double *m1, const float *m2, float *m3) { double m2r0 = m2[0]; double m2r1 = m2[1]; double m2r2 = m2[2]; m3[0] = (float) (m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2 + m1[3]); m3[1] = (float) (m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2 + m1[7]); m3[2] = (float) (m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2 + m1[11]); } void transform44d3d(const double *m1, const double *m2, double *m3) { double m2r0 = m2[0]; double m2r1 = m2[1]; double m2r2 = m2[2]; m3[0] = (float) (m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2 + m1[3]); m3[1] = (float) (m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2 + m1[7]); m3[2] = (float) (m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2 + m1[11]); } void transform44d3fas33d3f(const double *m1, const float *m2, float *m3) { double m2r0 = m2[0]; double m2r1 = m2[1]; double m2r2 = m2[2]; m3[0] = (float) (m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2); m3[1] = (float) (m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2); m3[2] = (float) (m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2); } // same as MatrixInvTransformC44fAs33f3f void transform44f3fas33f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; m3[0] = (m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2); m3[1] = (m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2); m3[2] = (m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2); } void inverse_transformC44f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0] - m1[12]; float m2r1 = m2[1] - m1[13]; float m2r2 = m2[2] - m1[14]; m3[0] = (float) (m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2); m3[1] = (float) (m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2); m3[2] = (float) (m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2); } void inverse_transform44f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0] - m1[3]; float m2r1 = m2[1] - m1[7]; float m2r2 = m2[2] - m1[11]; m3[0] = (float) (m1[0] * m2r0 + m1[4] * m2r1 + m1[8] * m2r2); m3[1] = (float) (m1[1] * m2r0 + m1[5] * m2r1 + m1[9] * m2r2); m3[2] = (float) (m1[2] * m2r0 + m1[6] * m2r1 + m1[10] * m2r2); } void inverse_transform44d3f(const double *m1, const float *m2, float *m3) { double m2r0 = m2[0] - m1[3]; double m2r1 = m2[1] - m1[7]; double m2r2 = m2[2] - m1[11]; m3[0] = (float) (m1[0] * m2r0 + m1[4] * m2r1 + m1[8] * m2r2); m3[1] = (float) (m1[1] * m2r0 + m1[5] * m2r1 + m1[9] * m2r2); m3[2] = (float) (m1[2] * m2r0 + m1[6] * m2r1 + m1[10] * m2r2); } void inverse_transform44d3d(const double *m1, const double *m2, double *m3) { double m2r0 = m2[0] - m1[3]; double m2r1 = m2[1] - m1[7]; double m2r2 = m2[2] - m1[11]; m3[0] = (float) (m1[0] * m2r0 + m1[4] * m2r1 + m1[8] * m2r2); m3[1] = (float) (m1[1] * m2r0 + m1[5] * m2r1 + m1[9] * m2r2); m3[2] = (float) (m1[2] * m2r0 + m1[6] * m2r1 + m1[10] * m2r2); } void transform44f4f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; float m2r3 = m2[3]; m3[0] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2 + m1[3] * m2r3; m3[1] = m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2 + m1[7] * m2r3; m3[2] = m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2 + m1[11] * m2r3; m3[3] = m1[12] * m2r0 + m1[13] * m2r1 + m1[14] * m2r2 + m1[15] * m2r3; } void initializeTTT44f(float *m) { int a; for(a = 0; a < 16; a++) m[a] = _0; for(a = 0; a < 4; a++) m[4 * a + a] = _1; } void combineTTT44f44f(const float *m1, const float *m2, float *m3) /* WARNING: this routine is ill-conceived and essentially broken */ /* NOTE: this is NOT equivalent to 4x4 matrix multiplication. TTTs are designed for easily creating movies of rotating bodies! */ { float m1_homo[16]; float m2_homo[16]; const float *src; float *dst; float pre[3], post[3]; /* convert the existing TTT into a homogenous transformation matrix */ convertTTTfR44f(m1, m1_homo); convertTTTfR44f(m2, m2_homo); /* combine the matrices */ left_multiply44f44f(m1_homo, m2_homo); /* now use the origin from the most recent TTT */ src = m1 + 12; invert3f3f(src, pre); transform44f3fas33f3f(m2_homo, pre, post); m2_homo[3] += post[0]; m2_homo[7] += post[1]; m2_homo[11] += post[2]; dst = m2_homo + 12; copy3f(src, dst); copy44f(m2_homo, m3); } void convertTTTfR44d(const float *ttt, double *homo) { /* takes the PyMOL-specific TTT matrix and makes a homogenous 4x4 txf matrix homo of it */ double ttt_3 = (double) ttt[3]; double ttt_7 = (double) ttt[7]; double ttt_11 = (double) ttt[11]; double ttt_12 = (double) ttt[12]; double ttt_13 = (double) ttt[13]; double ttt_14 = (double) ttt[14]; /* dump44f(ttt,"ttt"); */ homo[0] = (double) ttt[0]; homo[1] = (double) ttt[1]; homo[2] = (double) ttt[2]; homo[4] = (double) ttt[4]; homo[5] = (double) ttt[5]; homo[6] = (double) ttt[6]; homo[8] = (double) ttt[8]; homo[9] = (double) ttt[9]; homo[10] = (double) ttt[10]; homo[3] = (homo[0] * ttt_12) + (homo[1] * ttt_13) + (homo[2] * ttt_14) + ttt_3; homo[7] = (homo[4] * ttt_12) + (homo[5] * ttt_13) + (homo[6] * ttt_14) + ttt_7; homo[11] = (homo[8] * ttt_12) + (homo[9] * ttt_13) + (homo[10] * ttt_14) + ttt_11; homo[12] = 0.0; homo[13] = 0.0; homo[14] = 0.0; homo[15] = 1.0; /* dump44d(homo, "homo"); */ } void convertTTTfR44f(const float *ttt, float *homo) { /* takes the PyMOL-specific TTT matrix and makes a homogenous 4x4 txf matrix homo of it */ float ttt_3 = ttt[3]; float ttt_7 = ttt[7]; float ttt_11 = ttt[11]; float ttt_12 = ttt[12]; float ttt_13 = ttt[13]; float ttt_14 = ttt[14]; homo[0] = ttt[0]; homo[1] = ttt[1]; homo[2] = ttt[2]; homo[4] = ttt[4]; homo[5] = ttt[5]; homo[6] = ttt[6]; homo[8] = ttt[8]; homo[9] = ttt[9]; homo[10] = ttt[10]; homo[3] = (homo[0] * ttt_12) + (homo[1] * ttt_13) + (homo[2] * ttt_14) + ttt_3; homo[7] = (homo[4] * ttt_12) + (homo[5] * ttt_13) + (homo[6] * ttt_14) + ttt_7; homo[11] = (homo[8] * ttt_12) + (homo[9] * ttt_13) + (homo[10] * ttt_14) + ttt_11; homo[12] = 0.0; homo[13] = 0.0; homo[14] = 0.0; homo[15] = 1.0; } void convert44d44f(const double *dbl, float *flt) { flt[0] = (float) dbl[0]; flt[1] = (float) dbl[1]; flt[2] = (float) dbl[2]; flt[3] = (float) dbl[3]; flt[4] = (float) dbl[4]; flt[5] = (float) dbl[5]; flt[6] = (float) dbl[6]; flt[7] = (float) dbl[7]; flt[8] = (float) dbl[8]; flt[9] = (float) dbl[9]; flt[10] = (float) dbl[10]; flt[11] = (float) dbl[11]; flt[12] = (float) dbl[12]; flt[13] = (float) dbl[13]; flt[14] = (float) dbl[14]; flt[15] = (float) dbl[15]; } void convert44f44d(const float *flt, double *dbl) { dbl[0] = (double) flt[0]; dbl[1] = (double) flt[1]; dbl[2] = (double) flt[2]; dbl[3] = (double) flt[3]; dbl[4] = (double) flt[4]; dbl[5] = (double) flt[5]; dbl[6] = (double) flt[6]; dbl[7] = (double) flt[7]; dbl[8] = (double) flt[8]; dbl[9] = (double) flt[9]; dbl[10] = (double) flt[10]; dbl[11] = (double) flt[11]; dbl[12] = (double) flt[12]; dbl[13] = (double) flt[13]; dbl[14] = (double) flt[14]; dbl[15] = (double) flt[15]; } void convertR44dTTTf(const double *homo, float *ttt) { /* nowadays, homogeneous matrices with (0,0,0,1) in 4th row are TTT compatible */ convert44d44f(homo, ttt); } void multiply44d44d44d(const double *left, const double *right, double *product) { double rA = right[0]; double rB = right[4]; double rC = right[8]; double rD = right[12]; product[0] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[4] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[8] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[12] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[1]; rB = right[5]; rC = right[9]; rD = right[13]; product[1] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[5] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[9] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[13] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[2]; rB = right[6]; rC = right[10]; rD = right[14]; product[2] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[6] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[10] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[14] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[3]; rB = right[7]; rC = right[11]; rD = right[15]; product[3] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[7] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[11] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[15] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; } void left_multiply44d44d(const double *left, double *right) { double rA = right[0]; double rB = right[4]; double rC = right[8]; double rD = right[12]; right[0] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[4] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[8] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[12] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[1]; rB = right[5]; rC = right[9]; rD = right[13]; right[1] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[5] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[9] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[13] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[2]; rB = right[6]; rC = right[10]; rD = right[14]; right[2] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[6] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[10] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[14] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[3]; rB = right[7]; rC = right[11]; rD = right[15]; right[3] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[7] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[11] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[15] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; } void right_multiply44d44d(double *left, const double *right) { double cA = left[0]; double cB = left[1]; double cC = left[2]; double cD = left[3]; left[0] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[1] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[2] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[3] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[4]; cB = left[5]; cC = left[6]; cD = left[7]; left[4] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[5] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[6] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[7] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[8]; cB = left[9]; cC = left[10]; cD = left[11]; left[8] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[9] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[10] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[11] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[12]; cB = left[13]; cC = left[14]; cD = left[15]; left[12] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[13] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[14] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[15] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; } void multiply44f44f44f(const float *left, const float *right, float *product) { float rA = right[0]; float rB = right[4]; float rC = right[8]; float rD = right[12]; product[0] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[4] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[8] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[12] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[1]; rB = right[5]; rC = right[9]; rD = right[13]; product[1] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[5] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[9] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[13] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[2]; rB = right[6]; rC = right[10]; rD = right[14]; product[2] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[6] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[10] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[14] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[3]; rB = right[7]; rC = right[11]; rD = right[15]; product[3] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; product[7] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; product[11] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; product[15] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; } void left_multiply44f44f(const float *left, float *right) { float rA = right[0]; float rB = right[4]; float rC = right[8]; float rD = right[12]; right[0] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[4] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[8] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[12] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[1]; rB = right[5]; rC = right[9]; rD = right[13]; right[1] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[5] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[9] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[13] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[2]; rB = right[6]; rC = right[10]; rD = right[14]; right[2] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[6] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[10] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[14] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; rA = right[3]; rB = right[7]; rC = right[11]; rD = right[15]; right[3] = left[0] * rA + left[1] * rB + left[2] * rC + left[3] * rD; right[7] = left[4] * rA + left[5] * rB + left[6] * rC + left[7] * rD; right[11] = left[8] * rA + left[9] * rB + left[10] * rC + left[11] * rD; right[15] = left[12] * rA + left[13] * rB + left[14] * rC + left[15] * rD; } void right_multiply44f44f(float *left, const float *right) { float cA = left[0]; float cB = left[1]; float cC = left[2]; float cD = left[3]; left[0] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[1] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[2] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[3] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[4]; cB = left[5]; cC = left[6]; cD = left[7]; left[4] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[5] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[6] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[7] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[8]; cB = left[9]; cC = left[10]; cD = left[11]; left[8] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[9] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[10] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[11] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; cA = left[12]; cB = left[13]; cC = left[14]; cD = left[15]; left[12] = cA * right[0] + cB * right[4] + cC * right[8] + cD * right[12]; left[13] = cA * right[1] + cB * right[5] + cC * right[9] + cD * right[13]; left[14] = cA * right[2] + cB * right[6] + cC * right[10] + cD * right[14]; left[15] = cA * right[3] + cB * right[7] + cC * right[11] + cD * right[15]; } void invert_special44d44d(const double *orig, double *inv) { /* inverse of the rotation matrix */ inv[0] = orig[0]; inv[1] = orig[4]; inv[2] = orig[8]; inv[4] = orig[1]; inv[5] = orig[5]; inv[6] = orig[9]; inv[8] = orig[2]; inv[9] = orig[6]; inv[10] = orig[10]; /* invert the translation portion */ inv[3] = -(orig[3] * orig[0] + orig[7] * orig[4] + orig[11] * orig[8]); inv[7] = -(orig[3] * orig[1] + orig[7] * orig[5] + orig[11] * orig[9]); inv[11] = -(orig[3] * orig[2] + orig[7] * orig[6] + orig[11] * orig[10]); inv[12] = 0.0; inv[13] = 0.0; inv[14] = 0.0; inv[15] = 1.0; } void invert_special44f44f(const float *orig, float *inv) { /* inverse of the rotation matrix */ inv[0] = orig[0]; inv[1] = orig[4]; inv[2] = orig[8]; inv[4] = orig[1]; inv[5] = orig[5]; inv[6] = orig[9]; inv[8] = orig[2]; inv[9] = orig[6]; inv[10] = orig[10]; /* invert the translation portion */ inv[3] = -(orig[3] * orig[0] + orig[7] * orig[4] + orig[11] * orig[8]); inv[7] = -(orig[3] * orig[1] + orig[7] * orig[5] + orig[11] * orig[9]); inv[11] = -(orig[3] * orig[2] + orig[7] * orig[6] + orig[11] * orig[10]); inv[12] = 0.0F; inv[13] = 0.0F; inv[14] = 0.0F; inv[15] = 1.0F; } static void normalize3dp(double *v1, double *v2, double *v3) { double vlen = sqrt1d((v1[0] * v1[0]) + (v2[0] * v2[0]) + (v3[0] * v3[0])); if(vlen > R_SMALL) { v1[0] /= vlen; v2[0] /= vlen; v3[0] /= vlen; } else { v1[0] = _0; v2[1] = _0; v3[2] = _0; } } /* unused at present static void normalize3df( float *v1, float *v2, float *v3 ) { float vlen = (float)sqrt1f((v1[0]*v1[0]) + (v2[0]*v2[0]) + (v3[0]*v3[0])); if(vlen>R_SMALL) { v1[0]/=vlen; v2[0]/=vlen; v3[0]/=vlen; } else { v1[0]=_0; v2[1]=_0; v3[2]=_0; } } */ void scale3d(const double *v1, const double v0, double *v2) { v2[0] = v1[0] * v0; v2[1] = v1[1] * v0; v2[2] = v1[2] * v0; } void add3d(const double *v1, const double *v2, double *v3) { v3[0] = v1[0] + v2[0]; v3[1] = v1[1] + v2[1]; v3[2] = v1[2] + v2[2]; } void cross_product3d(const double *v1, const double *v2, double *cross) { cross[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); cross[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); cross[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); } void remove_component3d(const double *v1, const double *unit, double *result) { double dot; dot = v1[0] * unit[0] + v1[1] * unit[1] + v1[2] * unit[2]; result[0] = v1[0] - unit[0] * dot; result[1] = v1[1] - unit[1] * dot; result[2] = v1[2] - unit[2] * dot; } void reorient44d(double *matrix) { double tmp[16]; int a; /* restore orthogonality and recondition */ for(a = 0; a < 3; a++) { normalize3d(matrix); normalize3d(matrix + 4); normalize3d(matrix + 8); cross_product3d(matrix + 4, matrix + 8, tmp); cross_product3d(matrix + 8, matrix, tmp + 4); cross_product3d(matrix, matrix + 4, tmp + 8); normalize3d(tmp); normalize3d(tmp + 4); normalize3d(tmp + 8); scale3d(tmp, 2.0, tmp); scale3d(tmp + 4, 2.0, tmp + 4); scale3d(tmp + 8, 2.0, tmp + 8); add3d(matrix, tmp, tmp); add3d(matrix + 4, tmp + 4, tmp + 4); add3d(matrix + 8, tmp + 8, tmp + 8); copy3d(tmp, matrix); copy3d(tmp + 4, matrix + 4); copy3d(tmp + 8, matrix + 8); } normalize3d(matrix); normalize3d(matrix + 4); normalize3d(matrix + 8); copy3d(matrix, tmp); remove_component3d(matrix + 4, tmp, tmp + 4); cross_product3d(tmp, tmp + 4, tmp + 8); normalize3d(tmp + 4); normalize3d(tmp + 8); recondition44d(tmp); copy3d(tmp, matrix); copy3d(tmp + 4, matrix + 4); copy3d(tmp + 8, matrix + 8); } void recondition33d(double *matrix) { normalize3d(matrix); normalize3d(matrix + 3); normalize3d(matrix + 6); normalize3dp(matrix + 0, matrix + 3, matrix + 6); normalize3dp(matrix + 1, matrix + 4, matrix + 7); normalize3dp(matrix + 2, matrix + 5, matrix + 8); normalize3d(matrix); normalize3d(matrix + 3); normalize3d(matrix + 6); normalize3dp(matrix + 0, matrix + 3, matrix + 6); normalize3dp(matrix + 1, matrix + 4, matrix + 7); normalize3dp(matrix + 2, matrix + 5, matrix + 8); normalize3d(matrix); normalize3d(matrix + 3); normalize3d(matrix + 6); } void recondition44d(double *matrix) { normalize3d(matrix); normalize3d(matrix + 4); normalize3d(matrix + 8); normalize3dp(matrix + 0, matrix + 4, matrix + 8); normalize3dp(matrix + 1, matrix + 5, matrix + 9); normalize3dp(matrix + 2, matrix + 6, matrix + 10); normalize3d(matrix); normalize3d(matrix + 4); normalize3d(matrix + 8); normalize3dp(matrix + 0, matrix + 4, matrix + 8); normalize3dp(matrix + 1, matrix + 5, matrix + 9); normalize3dp(matrix + 2, matrix + 6, matrix + 10); normalize3d(matrix); normalize3d(matrix + 4); normalize3d(matrix + 8); } void invert_rotation_only44d44d(const double *orig, double *inv) { /* inverse of the rotation matrix */ inv[0] = orig[0]; inv[1] = orig[4]; inv[2] = orig[8]; inv[4] = orig[1]; inv[5] = orig[5]; inv[6] = orig[9]; inv[8] = orig[2]; inv[9] = orig[6]; inv[10] = orig[10]; inv[3] = 0.0; inv[7] = 0.0; inv[11] = 0.0; inv[12] = 0.0; inv[13] = 0.0; inv[14] = 0.0; inv[15] = 1.0; } void transformTTT44f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0] + m1[12]; float m2r1 = m2[1] + m1[13]; float m2r2 = m2[2] + m1[14]; m3[0] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2 + m1[3]; m3[1] = m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2 + m1[7]; m3[2] = m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2 + m1[11]; } void transform_normalTTT44f3f(const float *m1, const float *m2, float *m3) { float m2r0 = m2[0]; float m2r1 = m2[1]; float m2r2 = m2[2]; m3[0] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2; m3[1] = m1[4] * m2r0 + m1[5] * m2r1 + m1[6] * m2r2; m3[2] = m1[8] * m2r0 + m1[9] * m2r1 + m1[10] * m2r2; } void multiply33f33f(const float *m1, const float *m2, float *m3) { /* m2 and m3 can be the same matrix */ int a; float m2r0, m2r1, m2r2; for(a = 0; a < 3; a++) { m2r0 = m2[a]; m2r1 = m2[3 + a]; m2r2 = m2[6 + a]; m3[a] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2; m3[3 + a] = m1[3] * m2r0 + m1[4] * m2r1 + m1[5] * m2r2; m3[6 + a] = m1[6] * m2r0 + m1[7] * m2r1 + m1[8] * m2r2; } } void multiply33d33d(const double *m1, const double *m2, double *m3) { /* m2 and m3 can be the same matrix */ int a; double m2r0, m2r1, m2r2; for(a = 0; a < 3; a++) { m2r0 = m2[a]; m2r1 = m2[3 + a]; m2r2 = m2[6 + a]; m3[a] = m1[0] * m2r0 + m1[1] * m2r1 + m1[2] * m2r2; m3[3 + a] = m1[3] * m2r0 + m1[4] * m2r1 + m1[5] * m2r2; m3[6 + a] = m1[6] * m2r0 + m1[7] * m2r1 + m1[8] * m2r2; } } void matrix_multiply33f33f(Matrix33f m1, Matrix33f m2, Matrix33f m3) { multiply33f33f((float *) m1, (float *) m2, (float *) m3); } void matrix_multiply33d33d(Matrix33d m1, Matrix33d m2, Matrix33d m3) { multiply33d33d((double *) m1[0], (double *) m2, (double *) m3); } float deg_to_rad(float angle) { return ((float) ((angle * cPI) / 180.0)); } float rad_to_deg(float angle) { return ((float) (180.0 * (angle / cPI))); } void get_rotation_about3f3fTTTf(float angle, const float *dir, const float *origin, float *ttt) { float rot[9]; rotation_matrix3f(angle, dir[0], dir[1], dir[2], rot); ttt[0] = rot[0]; ttt[1] = rot[1]; ttt[2] = rot[2]; ttt[4] = rot[3]; ttt[5] = rot[4]; ttt[6] = rot[5]; ttt[8] = rot[6]; ttt[9] = rot[7]; ttt[10] = rot[8]; ttt[12] = -origin[0]; ttt[13] = -origin[1]; ttt[14] = -origin[2]; ttt[3] = origin[0]; ttt[7] = origin[1]; ttt[11] = origin[2]; ttt[15] = 1.0F; } void rotation_to_matrix33f(const float *axis, float angle, Matrix33f mat) { rotation_matrix3f(angle, axis[0], axis[1], axis[2], &mat[0][0]); } void rotation_matrix3f(float angle, float x, float y, float z, float *m) { /* returns a row-major rotation matrix */ int a, b; /* This function contributed by Erich Boleyn (erich@uruk.org) */ float mag, s, c; float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c; s = (float) sin(angle); c = (float) cos(angle); mag = (float) sqrt1f(x * x + y * y + z * z); if(mag >= R_SMALL) { x /= mag; y /= mag; z /= mag; #define M(row,col) m[row*3+col] xx = x * x; yy = y * y; zz = z * z; xy = x * y; yz = y * z; zx = z * x; xs = x * s; ys = y * s; zs = z * s; one_c = _1 - c; M(0, 0) = (one_c * xx) + c; M(0, 1) = (one_c * xy) - zs; M(0, 2) = (one_c * zx) + ys; M(1, 0) = (one_c * xy) + zs; M(1, 1) = (one_c * yy) + c; M(1, 2) = (one_c * yz) - xs; M(2, 0) = (one_c * zx) - ys; M(2, 1) = (one_c * yz) + xs; M(2, 2) = (one_c * zz) + c; } else { for(a = 0; a < 3; a++) for(b = 0; b < 3; b++) M(a, b) = 0; M(0, 0) = _1; M(1, 1) = _1; M(2, 2) = _1; } } #define get_angle USED_TO_RETURN_DEGREES float get_dihedral3f(const float *v0, const float *v1, const float *v2, const float *v3) { Vector3f d01, d21, d32, dd1, dd3, pos_d; float result = _0; subtract3f(v2, v1, d21); subtract3f(v0, v1, d01); subtract3f(v3, v2, d32); if(length3f(d21) < R_SMALL) { result = get_angle3f(d01, d32); } else { cross_product3f(d21, d01, dd1); cross_product3f(d21, d32, dd3); if((length3f(dd1) < R_SMALL) || (length3f(dd3) < R_SMALL)) { /* degenerate cases */ result = get_angle3f(d01, d32); /* fall back to angle between vectors */ } else { result = get_angle3f(dd1, dd3); cross_product3f(d21, dd1, pos_d); if(dot_product3f(dd3, pos_d) < _0) result = -result; } } return (result); } float get_angle3f(const float *v1, const float *v2) { double denom; double result; double arg1, arg2; arg1 = ((v1[0] * (double)v1[0]) + (v1[1] * (double)v1[1]) + (v1[2] * (double)v1[2])); arg2 = ((v2[0] * (double)v2[0]) + (v2[1] * (double)v2[1]) + (v2[2] * (double)v2[2])); denom = sqrt1d(arg1) * sqrt1d(arg2); if(denom > R_SMALL){ arg1 = (v1[0] * (double)v2[0] + v1[1] * (double)v2[1] + v1[2] * (double)v2[2]); result = arg1 / denom; } else result = _0; if(result < -_1) result = -_1; else if(result > _1) result = _1; return acosf(result); } void normalize23f(const float *v1, float *v2) { double vlen; vlen = length3f(v1); if(vlen > R_SMALL) { v2[0] = (float) (v1[0] / vlen); v2[1] = (float) (v1[1] / vlen); v2[2] = (float) (v1[2] / vlen); } else { v2[0] = _0; v2[1] = _0; v2[2] = _0; } } void clamp3f(float *v1) { if(v1[0] < _0) v1[0] = _0; if(v1[0] > _1) v1[0] = _1; if(v1[1] < _0) v1[1] = _0; if(v1[1] > _1) v1[1] = _1; if(v1[2] < _0) v1[2] = _0; if(v1[2] > _1) v1[2] = _1; } void normalize3d(double *v1) { double vlen; vlen = length3d(v1); if(vlen > R_SMALL) { v1[0] /= vlen; v1[1] /= vlen; v1[2] /= vlen; } else { v1[0] = _0; v1[1] = _0; v1[2] = _0; } } void normalize2f(float *v1) { double vlen; vlen = length2f(v1); if(vlen > R_SMALL) { v1[0] /= vlen; v1[1] /= vlen; } else { v1[0] = _0; v1[1] = _0; } } void normalize4f(float *v1) { v1[0] /= v1[3]; v1[1] /= v1[3]; v1[2] /= v1[3]; v1[3] = 1.f; } double length3d(const double *v1) { return (sqrt1d((v1[0] * v1[0]) + (v1[1] * v1[1]) + (v1[2] * v1[2]))); } double distance_line2point3f(const float *base, const float *normal, const float *point, float *alongNormalSq) { float hyp[3], adj[3]; double result; hyp[0] = point[0] - base[0]; hyp[1] = point[1] - base[1]; hyp[2] = point[2] - base[2]; project3f(hyp, normal, adj); (*alongNormalSq) = ((adj[0] * adj[0]) + (adj[1] * adj[1]) + (adj[2] * adj[2])); result = ((hyp[0] * hyp[0]) + (hyp[1] * hyp[1]) + (hyp[2] * hyp[2])) - (*alongNormalSq); if(result <= _0) return (_0); else return (sqrt1d(result)); } double distance_halfline2point3f(const float *base, const float *normal, const float *point, float *alongNormalSq) { float hyp[3], adj[3]; double result; hyp[0] = point[0] - base[0]; hyp[1] = point[1] - base[1]; hyp[2] = point[2] - base[2]; if(project3f(hyp, normal, adj) > _0) { (*alongNormalSq) = ((adj[0] * adj[0]) + (adj[1] * adj[1]) + (adj[2] * adj[2])); result = ((hyp[0] * hyp[0]) + (hyp[1] * hyp[1]) + (hyp[2] * hyp[2])) - (*alongNormalSq); if(result <= _0) return (_0); else return (sqrt1d(result)); } else { return (MAXFLOAT); } } void matrix_transform33f3f(const Matrix33f m1, const float *v1, float *v2) { v2[0] = m1[0][0] * v1[0] + m1[0][1] * v1[1] + m1[0][2] * v1[2]; v2[1] = m1[1][0] * v1[0] + m1[1][1] * v1[1] + m1[1][2] * v1[2]; v2[2] = m1[2][0] * v1[0] + m1[2][1] * v1[1] + m1[2][2] * v1[2]; } void matrix_inverse_transform33f3f(const Matrix33f m1, const float *v1, float *v2) { v2[0] = m1[0][0] * v1[0] + m1[1][0] * v1[1] + m1[2][0] * v1[2]; v2[1] = m1[0][1] * v1[0] + m1[1][1] * v1[1] + m1[2][1] * v1[2]; v2[2] = m1[0][2] * v1[0] + m1[1][2] * v1[1] + m1[2][2] * v1[2]; } #if 0 double matdiffsq(float *v1, oMatrix5f m, float *v2) { double dx, dy, dz; float vx, vy, vz; dx = v2[0] - m[3][0]; dy = v2[1] - m[3][1]; dz = v2[2] - m[3][2]; vx = m[0][0] * dx + m[0][1] * dy + m[0][2] * dz; vy = m[1][0] * dx + m[1][1] * dy + m[1][2] * dz; vz = m[2][0] * dx + m[2][1] * dy + m[2][2] * dz; dx = (v1[0] - (vx + m[4][0])); dy = (v1[1] - (vy + m[4][1])); dz = (v1[2] - (vz + m[4][2])); return (dx * dx + dy * dy + dz * dz); } #endif void transform5f3f(const oMatrix5f m, const float *v1, float *v2) { double dx, dy, dz; double vx, vy, vz; dx = v1[0] - m[3][0]; dy = v1[1] - m[3][1]; dz = v1[2] - m[3][2]; vx = m[0][0] * dx + m[0][1] * dy + m[0][2] * dz; vy = m[1][0] * dx + m[1][1] * dy + m[1][2] * dz; vz = m[2][0] * dx + m[2][1] * dy + m[2][2] * dz; v2[0] = (((float) vx) + m[4][0]); v2[1] = (((float) vy) + m[4][1]); v2[2] = (((float) vz) + m[4][2]); } void transform3d3f(const oMatrix3d m1, const float *v1, float *v2) { int b; for(b = 0; b < 3; b++) v2[b] = m1[b][0] * v1[0] + m1[b][1] * v1[1] + m1[b][2] * v1[2]; } void transform33d3f(const Matrix33d m1, const float *v1, float *v2) { int b; for(b = 0; b < 3; b++) v2[b] = (float) (m1[b][0] * v1[0] + m1[b][1] * v1[1] + m1[b][2] * v1[2]); } /* void matcopy ( oMatrix5f to,oMatrix5f from ) { int a,b; for(a=0;a<5;a++) for(b=0;b<3;b++) to[a][b] = from[a][b]; } void mattran ( oMatrix5f nm, oMatrix5f om, int axis, float dist ) { matcopy(nm,om); nm[4][axis] += dist; } void matrot ( oMatrix5f nm, oMatrix5f om, int axis, float angle ) { oMatrix5f rm; float ca,sa; int a,b; ca = cos(angle); sa = sin(angle); switch(axis) { case 0: rm[0][0] = _1; rm[0][1] = _0; rm[0][2] = _0; rm[1][0] = _0; rm[1][1] = ca; rm[1][2] = sa; rm[2][0] = _0; rm[2][1] = -sa; rm[2][2] = ca; break; case 1: rm[0][0] = ca; rm[0][1] = _0; rm[0][2] = -sa; rm[1][0] = _0; rm[1][1] = _1; rm[1][2] = _0; rm[2][0] = sa; rm[2][1] = _0; rm[2][2] = ca; break; case 2: rm[0][0] = ca; rm[0][1] = sa; rm[0][2] = _0; rm[1][0] = -sa; rm[1][1] = ca; rm[1][2] = _0; rm[2][0] = _0; rm[2][1] = _0; rm[2][2] = _1; break; } for(a=0;a<3;a++) { nm[3][a] = om[3][a]; nm[4][a] = om[4][a]; for(b=0;b<3;b++) nm[a][b] = rm[a][0]*om[0][b] + rm[a][1]*om[1][b] + rm[a][2]*om[2][b]; } normalize3f(nm[0]); normalize3f(nm[1]); normalize3f(nm[2]); } */ void rotation_to_matrix(Matrix53f rot, const float *axis, float angle) { rotation_matrix3f(angle, axis[0], axis[1], axis[2], &rot[0][0]); } static void find_axis(Matrix33d a, float *axis) { doublereal at[3][3], v[3][3], vt[3][3], fv1[3][3]; integer iv1[3]; integer ierr; integer nm, n, matz; doublereal wr[3], wi[3]; /*p[3][3]; */ int x, y; nm = 3; n = 3; matz = 1; recondition33d(&a[0][0]); /* IMPORTANT! */ for(x = 0; x < 3; x++) { for(y = 0; y < 3; y++) { at[y][x] = a[x][y]; } } pymol_rg_(&nm, &n, &at[0][0], wr, wi, &matz, &vt[0][0], iv1, &fv1[0][0], &ierr); for(x = 0; x < 3; x++) { for(y = 0; y < 3; y++) { v[y][x] = vt[x][y]; } } axis[0] = 0.0F; axis[1] = 0.0F; axis[2] = 0.0F; { doublereal max_real = 0.0F, test_real; doublereal min_imag = 1.0F, test_imag; float test_inp[3], test_out[3]; for(x = 0; x < 3; x++) { /* looking for an eigvalue of (1,0) */ /* printf("wr %8.3f wi %8.3f\n",wr[x],wi[x]); printf("%8.3f %8.3f %8.3f\n", v[0][x],v[1][x],v[2][x]); */ test_real = fabs(wr[x]); test_imag = fabs(wi[x]); if((test_real >= max_real) && (test_imag <= min_imag)) { for(y = 0; y < 3; y++) test_inp[y] = (float) v[y][x]; transform33d3f(a, test_inp, test_out); /* confirm that axis is invariant to rotation */ test_out[0] -= test_inp[0]; test_out[1] -= test_inp[1]; test_out[2] -= test_inp[2]; if((test_out[0] * test_out[0] + test_out[1] * test_out[1] + test_out[2] * test_out[2]) < 0.1) { for(y = 0; y < 3; y++) axis[y] = test_inp[y]; max_real = test_real; min_imag = test_imag; } } else { /*for(y=0;y<3;y++) v[y][x]=_0; */ } } } /* printf("eigenvectors\n%8.3f %8.3f %8.3f\n",v[0][0],v[0][1],v[0][2]); printf("%8.3f %8.3f %8.3f\n",v[1][0],v[1][1],v[1][2]); printf("%8.3f %8.3f %8.3f\n",v[2][0],v[2][1],v[2][2]); printf("eigenvalues\n%8.3f %8.3f %8.3f\n",wr[0],wr[1],wr[2]); printf("%8.3f %8.3f %8.3f\n",wi[0],wi[1],wi[2]); */ /* matrix_multiply33d33d(a,v,p); printf("invariance\n"); printf("%8.3f %8.3f %8.3f\n",p[0][0],p[0][1],p[0][2]); printf("%8.3f %8.3f %8.3f\n",p[1][0],p[1][1],p[1][2]); printf("%8.3f %8.3f %8.3f\n",p[2][0],p[2][1],p[2][2]); */ } void matrix_to_rotation(Matrix53f rot, float *axis, float *angle) { float perp[3], tmp[3], rperp[3], dirck[3]; Matrix33d rot3d; Matrix53f rotck; int a, b; #ifdef MATCHK printf("starting matrix\n"); for(a = 0; a < 3; a++) printf("%8.3f %8.3f %8.3f\n", rot[a][0], rot[a][1], rot[a][2]); #endif for(a = 0; a < 3; a++) for(b = 0; b < 3; b++) rot3d[a][b] = (double) rot[a][b]; find_axis(rot3d, axis); /* find a perpendicular vector */ perp[0] = axis[1] * axis[0] - axis[2] * axis[2]; perp[1] = axis[2] * axis[1] - axis[0] * axis[0]; perp[2] = axis[0] * axis[2] - axis[1] * axis[1]; if(length3f(perp) < R_SMALL) { tmp[0] = axis[0]; tmp[1] = -2 * axis[1]; tmp[2] = axis[2]; cross_product3f(axis, tmp, perp); } normalize3f(perp); transform33d3f(rot3d, perp, rperp); *angle = get_angle3f(perp, rperp); cross_product3f(perp, rperp, dirck); if(((dirck[0] * axis[0]) + (dirck[1] * axis[1]) + (dirck[2] * axis[2])) < _0) *angle = -*angle; /* printf("angle %8.3f \n",*angle); */ rotation_to_matrix(rotck, axis, *angle); #ifdef MATCHK printf("reconstructed matrix: \n"); for(a = 0; a < 3; a++) printf("%8.3f %8.3f %8.3f\n", rotck[a][0], rotck[a][1], rotck[a][2]); printf("\n"); #endif } void mult3f(const float *vsrc, const float val, float *vdest){ vdest[0] = vsrc[0] * val; vdest[1] = vsrc[1] * val; vdest[2] = vsrc[2] * val; } void mult4f(const float *vsrc, const float val, float *vdest){ vdest[0] = vsrc[0] * val; vdest[1] = vsrc[1] * val; vdest[2] = vsrc[2] * val; vdest[3] = vsrc[3] * val; } float max3(float val1, float val2, float val3){ if (val1>val2){ if (val1>val3){ return val1; } else { return val3; } } else { if (val2>val3){ return val2; } else { return val3; } } } float ave3(float val1, float val2, float val3){ return ((val1+val2+val3)/3.f); } float ave2(float val1, float val2){ return ((val1+val2)/2.f); } void white4f(float *rgba, float value){ rgba[0] = value; rgba[1] = value; rgba[2] = value; rgba[3] = 1.0F; } void add4f(const float *v1, const float *v2, float *v3) { v3[0] = v1[0] + v2[0]; v3[1] = v1[1] + v2[1]; v3[2] = v1[2] + v2[2]; v3[3] = v1[3] + v2[3]; } int countchrs(const char *str, char ch){ int cnt = 0; const char *tmp = str; while((tmp = strchr(tmp, ch))) { cnt++; tmp++; } return cnt; } /* * sigmoid smoothstep function with * smooth(0) = 0 * smooth(1) = 1 * smooth'(0) = 0 * smooth'(1) = 0 */ float smooth(float x, float power) { if(x <= 0.5F) { if(x <= 0.0F) return 0.0F; return 0.5F * powf(2.0F * x, power); } if(x >= 1.0F) return 1.0F; return 1.0F - (0.5F * powf(2.0F * (1.0F - x), power)); } /* Divides the unit circle radially into n segments with n >= 3. */ void subdivide(int n, float *x, float *y) { int a; if(n < 3) { n = 3; } for(a = 0; a <= n; a++) { x[a] = (float) cos(a * 2 * PI / n); y[a] = (float) sin(a * 2 * PI / n); } }