
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.141592654
#endif

float veclen(float *a)
{
      float vl;
      double tot;

      tot = a[0]*a[0]+a[1]*a[1]+a[2]*a[2];

      vl = 0.0;
      if (tot > 0.0) vl = (float) sqrt(tot);

      return(vl);

}

void vecnrm(float *v)
{
   float vl;
   int j;

   vl = veclen(v);
   if (vl != 0.0) {
      for (j=0; j<3; j++) {
	v[j] = v[j] / vl;
      }
   }
}
   
void IMPRD(float *a, float *b, float *c,int norm)
{
      int i;
      float rimp, al, bl;

      rimp = 0.0;

      for (i=0; i<3; i++) rimp = rimp + a[i]*b[i];

      al = veclen(a);
      bl = veclen(b);

      if (al > 0.0 && bl > 0.0) {
	 if (norm) {
            *c = rimp / (al*bl);
	 } else {
            *c = rimp;
	 }
      } else {
         *c = 0.0;
      }

}

void cross(float *a,float *b, float *c)
{
/*

       calculates cross product:   a x b = c
                                   -   -   -
*/
 
      c[0] = a[1]*b[2] - a[2]*b[1];
      c[1] = a[2]*b[0] - a[0]*b[2];
      c[2] = a[0]*b[1] - a[1]*b[0];

}

void xyzROT4(R,vt)
double R[4][4];
float *vt;
{
   int j,k;
   double p[4],pp[4];

   for (j=0; j<3; j++) {
	p[j] = vt[j];
	pp[j] = 0.0;
   }

   p[3] = 1.0;
   for (j=0; j<3; j++) {
	for (k=0; k<4; k++) {
	   pp[j] = pp[j] + R[j][k]*p[k];
	}
   }

   for (j=0; j<3; j++) {
	vt[j] = (float) pp[j];
   }
}

void Frst_Rot(cc,uu,sina,cosa,R)
float *cc;
float *uu;
double sina;
double cosa;
double R[4][4];
{
// rotate around an arbitary vector in space (uu) from the center (cc)
// angle to rotate around defined by sina and cosa
// the uu vector NEEDS to be normalized !!!

    int i,j;
    double ca,sa,c[3],u[3];

    ca = cosa;
    sa = sina;

    for (i = 0; i<3; i++ ) {
	c[i] = (double) cc[i];
	u[i] = (double) uu[i];
    }

    R[0][0] = u[0]*u[0] + (u[1]*u[1] + u[2]*u[2])*ca;
    R[0][1] = u[0]*u[1]*(1.0 - ca) - u[2]*sa;
    R[0][2] = u[0]*u[2]*(1.0 - ca) + u[1]*sa;
    R[0][3] = (c[0]*(u[1]*u[1]+u[2]*u[2])-u[0]*(c[1]*u[1]+c[2]*u[2]))*(1.0 - ca) + (c[1]*u[2] - c[2]*u[1])*sa;

    R[1][0] = u[0]*u[1]*(1.0 - ca) + u[2]*sa;
    R[1][1] = u[1]*u[1] + (u[0]*u[0] + u[2]*u[2])*ca;
    R[1][2] = u[1]*u[2]*(1.0 - ca) - u[0]*sa;
    R[1][3] = (c[1]*(u[0]*u[0]+u[2]*u[2])-u[1]*(c[0]*u[0]+c[2]*u[2]))*(1.0 - ca) + (c[2]*u[0] - c[0]*u[2])*sa;

    R[2][0] = u[0]*u[2]*(1.0 - ca) - u[1]*sa;
    R[2][1] = u[1]*u[2]*(1.0 - ca) + u[0]*sa;
    R[2][2] = u[2]*u[2] + (u[0]*u[0] + u[1]*u[1])*ca;
    R[2][3] = (c[2]*(u[0]*u[0]+u[1]*u[1])-u[2]*(c[0]*u[0]+c[1]*u[1]))*(1.0 - ca) + (c[0]*u[1] - c[1]*u[0])*sa;

    R[3][0] = 0.0;
    R[3][1] = 0.0;
    R[3][2] = 0.0;
    R[3][3] = 1.0;
}

/*
void WrtRot(char *str,TRISTRU *TriR,int deg)
{
   int i,j;
   char longstr[MAXSTRLEN];
   TRISTRU *Tri[1];

   Tri[0] = TriR;

   sprintf(longstr,"%s_%03d.mol2",str,deg);
   Write_Results(longstr,Tri,1,&DCKxyz,2,0);
}
*/

#define PI 3.14159265

void do360(float *v1, float *v2, float *v3, float *Cen)
{
   int i,j,k,l,degI;
   float pt[3],Rotv2[3];
   double cosa,sina;
   float ca,sa,tang,atang,val;
   double deg,rad;
   double R[4][4];

   val = 180.0 / PI;

// loop over angles 0.0 to 350.0 degrees for rotation around v2

   for (k=0; k<36; k++) {

     degI = k*10;
     deg = (double) degI;
     rad = deg*(M_PI/180.0);

     sina = sin(rad);
     cosa = cos(rad);

// both sina,cosa and cosa,sina give wrong rotations

     Frst_Rot(Cen,v1,cosa,sina,R);

     for (j=0; j<3; j++) {
	pt[j] = v2[j] + Cen[j];
     }

     xyzROT4(R,pt);

     for (j=0; j<3; j++) {
	Rotv2[j] = pt[j] - Cen[j];
     }

     ca = 0.0; sa = 0.0;
     IMPRD(v1,Rotv2,&ca,1);
     IMPRD(v3,Rotv2,&sa,1);

     tang = sa / ca;
     atang = atan(tang) * val;

     fprintf(stderr,"360: degI %d ca %.3f sa %.3f atang %.3f\n",degI,ca,sa,atang);
     if (1.0 - ca < 0.05) {
	fprintf(stderr,"360: degI %d 1-cosa %.3f\n",degI,1.0 - ca);
	fprintf(stderr,"360: RotV2 %.3f %.3f %.3f\n",Rotv2[0],Rotv2[1],Rotv2[2]);
     }

// write rotated coordinates around v2 to Rot*.mol2

//     WrtRot("Rot",Tri,degI);


   } // end for k
}

int main(int argc, char *argv[]) {
   int i,j,k,l;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float cosa,sina,csa,ca,sa,tang,atang,val;
   double R1[4][4];
   float Cen[3],p1c[3],p2c[3],p3c[3];

	val = 180.0 / PI;

// v1 is the protein triangle center
// v2 is the ligand  triangle center

	v1[0] =  0.355; v1[1] = -0.066; v1[2] = -0.932;
	v2[0] = -0.441; v2[1] = -0.886; v2[2] =  0.141;
	Cen[0] = 61.992; Cen[1] = 23.497; Cen[2] = 53.625;

	p1c[0] =  67.369; p1c[1] = 34.295; p1c[2] =  51.908;
	p2c[0] =  56.615; p2c[1] = 12.699; p2c[2] =  55.341;
	p3c[0] =  64.654; p3c[1] = 28.839; p3c[2] =  52.695;

	vecnrm(v1);
	vecnrm(v2);

// V3 perpendicular to v1 and v2

	cross(v1,v2,V3);

fprintf(stderr,"V3 %.3f %.3f %.3f\n",V3[0],V3[1],V3[2]);

// v3 perpendicular to v1 and V3

	cross(v1,V3,v3);

fprintf(stderr,"v3 %.3f %.3f %.3f\n",v3[0],v3[1],v3[2]);

	IMPRD(v1,v2,&cosa,1);
 	IMPRD(v2,v3,&sina,1);

	tang = sina / cosa;
	atang = atan(tang) * val;

fprintf(stderr,"cosa %.3f sina %.3f angle degrees %.3f\n",cosa,sina,atang);

	Frst_Rot(Cen,v1,sina,cosa,R1);

	xyzROT4(R1,p1c);
	xyzROT4(R1,p2c);
	xyzROT4(R1,p3c);

fprintf(stderr,"rotated p1c %.3f %.3f %.3f\n", p1c[0],p1c[1],p1c[2]);
fprintf(stderr,"rotated p2c %.3f %.3f %.3f\n", p2c[0],p2c[1],p2c[2]);
fprintf(stderr,"rotated p3c %.3f %.3f %.3f\n", p3c[0],p3c[1],p3c[2]);

	do360(v1,v2,v3,Cen);

//   if (Tri2->spec == 1) {
//	WrtTri12(Tri1,Tri2);
//	R3calc(Tri1,Tri2,cooTri1AD0,cooTri2AD0);
//   }
}
