///////////////////////////////////////////////////////////////////////////// // Function: PositionAtom // Purpose: Given an atom object, sets the coordinates to be consistent with // the given bond length and angle // Input: Two atoms, with the first atom is bonded to the new atom and the // second atom bonded to the first. // The distance in angstroms between the new atom and the first atom // The angle in degrees between the new atom, the first atom, and the // second atom // Output: Writes new coordinates to the atom object // Requires: ///////////////////////////////////////////////////////////////////////////// void PositionAtom(MIAtom *atom, const MIAtom *root1, const MIAtom *root2, float length, float angle) { double cosba = cos(DEG2RAD * angle); double sinba = sin(DEG2RAD * angle); //Calculate the bond vector: the unit vector along the bond from root1 to root2 double bv[3]; BondVector(root1, root2, bv); NormVect(bv, bv); //Construct an orthogonal vector: a unit vector that is orthogonal to the bond vector double ov[3]; ov[0] = -bv[1]; ov[1] = bv[0]; ov[2] = 0; NormVect(ov, ov); //Position the atom along the vector (cosba * bv + sinba * ov) atom->setPosition((float)(root1->x() + length * (bv[0] * cosba + ov[0] * sinba)), (float)(root1->y() + length * (bv[1] * cosba + ov[1] * sinba)), (float)(root1->z() + length * (bv[2] * cosba))); //note that ov[2] = 0 }
static void Q_refl(STri *t, STri *tnew) { DPoint n; /* reflect vert 2 in line connecting vert 0 and 1 */ tnew->p[0] = t->p[0]; tnew->p[1] = t->p[1]; DCrossProd(&n.x, &t->p[0].x, &t->p[1].x); NormVect(&n.x); ReflVect(&tnew->p[2].x,&t->p[2].x,&n.x); ReflVect(&tnew->v.x,&t->v.x,&n.x); reg_vert(&tnew->v); }
///////////////////////////////////////////////////////////////////////////// // Function: PositionAtom // Purpose: Given an atom object, sets the coordinates to be consistent // with the given internal coordinates // Input: Three atoms, generally the first atom is bonded to the new atom // The distance in angstroms between the new atom and "root1" // The angle in degrees between the new atom, root1, and root2 // The dihedral angle between all four atoms, around the root1-root2 bond // Output: Writes new coordinates to the atom object // Requires: Note that if root1, root2, and root3 are collinear atoms, the // the atom position is underdetermined, because the dihedral angle // is meaningless ///////////////////////////////////////////////////////////////////////////// void PositionAtom(MIAtom *atom, const MIAtom *root1, const MIAtom *root2, const MIAtom *root3, float length, float angle, float torsion) { atom->setPosition(root1->x(), root1->y(), root1->z()); //Start new atom on top of the previous atom double cosba = cos(DEG2RAD * angle); double sinba = sin(DEG2RAD * angle); double v[3], temp[3]; //set v to be the unit vector from the BondVector(root1, root2, v); //attachment pt to a connected atom NormVect(v, v); atom->translate((float)(v[0] * cosba * length), //Move to an arbitrary point (float)(v[1] * cosba * length), //with the correct bond length (float)(v[2] * cosba * length)); //and angle. temp[0] = -v[1]; temp[1] = v[0]; temp[2] = 0; NormVect(temp, temp); atom->translate((float)(temp[0] * sinba * length), (float)(temp[1] * sinba * length), 0.0f); //Have chosen delta(z)=0 double chi; chi = CalcAtomTorsion(root3, root2, root1, atom); //Get the current torsion value RotateAtom(root2, root1, atom, torsion-(float)chi); }
static int MakeHedron(int np, int dp, int nq, int dq, double cp, double cq) { STri t0; double pang,qang,cosp,cosq,sinp,sinq; #ifdef DBG printf("MakeHedron: p = %d/%d q = %d/%d cp = %.4f cq = %.4f\n",np,dp,nq,dq,cp,cq); #endif nregtris = nfaces = nverts = 0; center_verts = state.verts>0?1:0; subdiv_sides = state.verts==2?1:0; nsides[0] = 4; nsides[1] = np; nsides[2] = nq; /* these are two of the angles of a right spherical triangle */ pang = PI*(double)dp/(double)np; qang = PI*(double)dq/(double)nq; /* compute the (sin,cos) of sides of the spherical triangle */ cosp = cos(pang)/sin(qang); cosq = cos(qang)/sin(pang); sinp = sqrt(1.0-cosp*cosp); sinq = sqrt(1.0-cosq*cosq); t0.p[0].x = 0.0; t0.p[0].y = 0.0; t0.p[0].z = 1.0; t0.p[1].x = sinq; t0.p[1].y = 0.0; t0.p[1].z = cosq; t0.p[2].x = 0.0; t0.p[2].y = sinp; t0.p[2].z = cosp; t0.v.x = cq*sinq; t0.v.y = cp*sinp; t0.v.z = 1.0 + cq*(cosq-1.0) + cp*(cosp-1.0); NormVect(&t0.v.x); #ifdef DBG printf(" pang = %.5f, qang = %.5f \n", RadToDeg(pang), RadToDeg(qang)); printf(" cpa = %.5f, cqa = %.5f\n", RadToDeg(acos(cosp)),RadToDeg(acos(cosq))); printf(" t = (%.4f,%.4f,%.4f) \n",t0.v.x,t0.v.y,t0.v.z); #endif switch(state.axis) { case 1: /* want P aligned with Z -- rotate into pos*/ RotY(&t0.p[0],-sinq,cosq); RotY(&t0.p[1],-sinq,cosq); RotY(&t0.p[2],-sinq,cosq); RotY(&t0.v,-sinq,cosq); break; case 2: /* Q aligned with Z -- */ RotX(&t0.p[0],sinp,cosp); RotX(&t0.p[1],sinp,cosp); RotX(&t0.p[2],sinp,cosp); RotX(&t0.v,sinp,cosp); break; } #ifdef DBG printf(" p0 = %.4f, %.4f, %.4f \n",t0.p[0].x,t0.p[0].y,t0.p[0].z); printf(" p1 = %.4f, %.4f, %.4f \n",t0.p[1].x,t0.p[1].y,t0.p[1].z); printf(" p2 = %.4f, %.4f, %.4f \n",t0.p[2].x,t0.p[2].y,t0.p[2].z); printf(" v = %.4f, %.4f, %.4f \n",t0.v.x,t0.v.y,t0.v.z); #endif memset(axis,0,3*sizeof(AxisList)); reg_vert(&t0.v); level = 0; traverse(&t0, -1); do_axis[0] = do_axis[1] = do_axis[2] = 1; star_axis[0] = star_axis[1] = star_axis[2] = 0; if (dp>1) star_axis[1] = 1; if (dq>1) star_axis[2] = 1; if (cp==0||cq==0) do_axis[0] = 0; if (cp==0.0 && cq==1.0) do_axis[1] = 0; if (cp==1.0 && cq==0.0) do_axis[2] = 0; #ifdef DBG printf(" nsides = %d,%d,%d \n",nsides[0],nsides[1],nsides[2]); printf(" do_axis= %d,%d,%d \n",do_axis[0],do_axis[1],do_axis[2]); printf(" numaxis = %d,%d,%d \n",axis[0].num,axis[1].num,axis[2].num); printf(" nverts = %d \n",nverts); printf(" ------------------ MakeHedron done -----------------\n"); #endif return(1); }