double calculateCosY(const RDGeom::Point3D &iPoint, const RDGeom::Point3D &jPoint, const RDGeom::Point3D &kPoint, const RDGeom::Point3D &lPoint) { RDGeom::Point3D rJI = iPoint - jPoint; RDGeom::Point3D rJK = kPoint - jPoint; RDGeom::Point3D rJL = lPoint - jPoint; rJI /= rJI.length(); rJK /= rJK.length(); rJL /= rJL.length(); RDGeom::Point3D n = rJI.crossProduct(rJK); n /= n.length(); return n.dotProduct(rJL); }
void testIssue216() { RDNumeric::DoubleSymmMatrix dmat(4); dmat.setVal(0, 0, 0.0); dmat.setVal(0, 1, 1.0); dmat.setVal(0, 2, 1.0); dmat.setVal(0, 3, 1.0); dmat.setVal(1, 1, 0.0); dmat.setVal(1, 2, 1.0); dmat.setVal(1, 3, 1.0); dmat.setVal(2, 2, 0.0); dmat.setVal(2, 3, 1.0); dmat.setVal(3, 3, 0.0); std::cout << dmat; RDGeom::PointPtrVect pos; for (int i = 0; i < 4; i++) { RDGeom::Point3D *pt = new RDGeom::Point3D(); pos.push_back(pt); } bool gotCoords = DistGeom::computeInitialCoords(dmat, pos); CHECK_INVARIANT(gotCoords, ""); for (int i = 1; i < 4; i++) { RDGeom::Point3D pti = *(RDGeom::Point3D *)pos[i]; for (int j = 0; j < i; j++) { RDGeom::Point3D ptj = *(RDGeom::Point3D *)pos[j]; ptj -= pti; CHECK_INVARIANT(RDKit::feq(ptj.length(), 1.0, 0.02), ""); } } }
double calcOopChi(const RDGeom::Point3D &iPoint, const RDGeom::Point3D &jPoint, const RDGeom::Point3D &kPoint, const RDGeom::Point3D &lPoint) { RDGeom::Point3D rJI = iPoint - jPoint; RDGeom::Point3D rJK = kPoint - jPoint; RDGeom::Point3D rJL = lPoint - jPoint; rJI /= rJI.length(); rJK /= rJK.length(); rJL /= rJL.length(); RDGeom::Point3D n = rJI.crossProduct(rJK); n /= n.length(); double sinChi = n.dotProduct(rJL); clipToOne(sinChi); return RAD2DEG * asin(sinChi); }
void setBondLength(Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, double value) { RDGeom::POINT3D_VECT &pos = conf.getPositions(); RANGE_CHECK(0, iAtomId, pos.size() - 1); RANGE_CHECK(0, jAtomId, pos.size() - 1); ROMol &mol = conf.getOwningMol(); Bond *bond = mol.getBondBetweenAtoms(iAtomId, jAtomId); if(!bond) throw ValueErrorException("atoms i and j must be bonded"); if(queryIsBondInRing(bond)) throw ValueErrorException("bond (i,j) must not belong to a ring"); RDGeom::Point3D v = pos[iAtomId] - pos[jAtomId]; double origValue = v.length(); if(origValue <= 1.e-8) throw ValueErrorException("atoms i and j have identical 3D coordinates"); // get all atoms bonded to j std::list<unsigned int> alist; _toBeMovedIdxList(mol, iAtomId, jAtomId, alist); v *= (value / origValue - 1.); for (std::list<unsigned int>::iterator it = alist.begin(); it != alist.end(); ++it) { pos[*it] -= v; } }
void InversionContrib::getGrad(double *pos, double *grad) const { PRECONDITION(dp_forceField, "no owner"); PRECONDITION(pos, "bad vector"); PRECONDITION(grad, "bad vector"); RDGeom::Point3D p1(pos[3 * d_at1Idx], pos[3 * d_at1Idx + 1], pos[3 * d_at1Idx + 2]); RDGeom::Point3D p2(pos[3 * d_at2Idx], pos[3 * d_at2Idx + 1], pos[3 * d_at2Idx + 2]); RDGeom::Point3D p3(pos[3 * d_at3Idx], pos[3 * d_at3Idx + 1], pos[3 * d_at3Idx + 2]); RDGeom::Point3D p4(pos[3 * d_at4Idx], pos[3 * d_at4Idx + 1], pos[3 * d_at4Idx + 2]); double *g1 = &(grad[3 * d_at1Idx]); double *g2 = &(grad[3 * d_at2Idx]); double *g3 = &(grad[3 * d_at3Idx]); double *g4 = &(grad[3 * d_at4Idx]); RDGeom::Point3D rJI = p1 - p2; RDGeom::Point3D rJK = p3 - p2; RDGeom::Point3D rJL = p4 - p2; double dJI = rJI.length(); double dJK = rJK.length(); double dJL = rJL.length(); if (isDoubleZero(dJI) || isDoubleZero(dJK) || isDoubleZero(dJL)) { return; } rJI /= dJI; rJK /= dJK; rJL /= dJL; RDGeom::Point3D n = (-rJI).crossProduct(rJK); n /= n.length(); double cosY = n.dotProduct(rJL); double sinYSq = 1.0 - cosY * cosY; double sinY = std::max(((sinYSq > 0.0) ? sqrt(sinYSq) : 0.0), 1.0e-8); double cosTheta = rJI.dotProduct(rJK); double sinThetaSq = std::max(1.0 - cosTheta * cosTheta, 1.0e-8); double sinTheta = std::max(((sinThetaSq > 0.0) ? sqrt(sinThetaSq) : 0.0), 1.0e-8); // sin(2 * W) = 2 * sin(W) * cos(W) = 2 * cos(Y) * sin(Y) double dE_dW = -d_forceConstant * (d_C1 * cosY - 4.0 * d_C2 * cosY * sinY); RDGeom::Point3D t1 = rJL.crossProduct(rJK); RDGeom::Point3D t2 = rJI.crossProduct(rJL); RDGeom::Point3D t3 = rJK.crossProduct(rJI); double term1 = sinY * sinTheta; double term2 = cosY / (sinY * sinThetaSq); double tg1[3] = { (t1.x / term1 - (rJI.x - rJK.x * cosTheta) * term2) / dJI, (t1.y / term1 - (rJI.y - rJK.y * cosTheta) * term2) / dJI, (t1.z / term1 - (rJI.z - rJK.z * cosTheta) * term2) / dJI }; double tg3[3] = { (t2.x / term1 - (rJK.x - rJI.x * cosTheta) * term2) / dJK, (t2.y / term1 - (rJK.y - rJI.y * cosTheta) * term2) / dJK, (t2.z / term1 - (rJK.z - rJI.z * cosTheta) * term2) / dJK }; double tg4[3] = { (t3.x / term1 - rJL.x * cosY / sinY) / dJL, (t3.y / term1 - rJL.y * cosY / sinY) / dJL, (t3.z / term1 - rJL.z * cosY / sinY) / dJL }; for (unsigned int i = 0; i < 3; ++i) { g1[i] += dE_dW * tg1[i]; g2[i] += -dE_dW * (tg1[i] + tg3[i] + tg4[i]); g3[i] += dE_dW * tg3[i]; g4[i] += dE_dW * tg4[i]; } }
void OopBendContrib::getGrad(double *pos, double *grad) const { PRECONDITION(dp_forceField, "no owner"); PRECONDITION(pos, "bad vector"); PRECONDITION(grad, "bad vector"); RDGeom::Point3D iPoint(pos[3 * d_at1Idx], pos[3 * d_at1Idx + 1], pos[3 * d_at1Idx + 2]); RDGeom::Point3D jPoint(pos[3 * d_at2Idx], pos[3 * d_at2Idx + 1], pos[3 * d_at2Idx + 2]); RDGeom::Point3D kPoint(pos[3 * d_at3Idx], pos[3 * d_at3Idx + 1], pos[3 * d_at3Idx + 2]); RDGeom::Point3D lPoint(pos[3 * d_at4Idx], pos[3 * d_at4Idx + 1], pos[3 * d_at4Idx + 2]); double *g1 = &(grad[3 * d_at1Idx]); double *g2 = &(grad[3 * d_at2Idx]); double *g3 = &(grad[3 * d_at3Idx]); double *g4 = &(grad[3 * d_at4Idx]); RDGeom::Point3D rJI = iPoint - jPoint; RDGeom::Point3D rJK = kPoint - jPoint; RDGeom::Point3D rJL = lPoint - jPoint; double dJI = rJI.length(); double dJK = rJK.length(); double dJL = rJL.length(); if (isDoubleZero(dJI) || isDoubleZero(dJK) || isDoubleZero(dJL)) { return; } rJI /= dJI; rJK /= dJK; rJL /= dJL; RDGeom::Point3D n = (-rJI).crossProduct(rJK); n /= n.length(); double const c2 = MDYNE_A_TO_KCAL_MOL * DEG2RAD * DEG2RAD; double sinChi = rJL.dotProduct(n); clipToOne(sinChi); double cosChiSq = 1.0 - sinChi * sinChi; double cosChi = std::max(((cosChiSq > 0.0) ? sqrt(cosChiSq) : 0.0), 1.0e-8); double chi = RAD2DEG * asin(sinChi); double cosTheta = rJI.dotProduct(rJK); clipToOne(cosTheta); double sinThetaSq = std::max(1.0 - cosTheta * cosTheta, 1.0e-8); double sinTheta = std::max(((sinThetaSq > 0.0) ? sqrt(sinThetaSq) : 0.0), 1.0e-8); double dE_dChi = RAD2DEG * c2 * d_koop * chi; RDGeom::Point3D t1 = rJL.crossProduct(rJK); RDGeom::Point3D t2 = rJI.crossProduct(rJL); RDGeom::Point3D t3 = rJK.crossProduct(rJI); double term1 = cosChi * sinTheta; double term2 = sinChi / (cosChi * sinThetaSq); double tg1[3] = {(t1.x / term1 - (rJI.x - rJK.x * cosTheta) * term2) / dJI, (t1.y / term1 - (rJI.y - rJK.y * cosTheta) * term2) / dJI, (t1.z / term1 - (rJI.z - rJK.z * cosTheta) * term2) / dJI}; double tg3[3] = {(t2.x / term1 - (rJK.x - rJI.x * cosTheta) * term2) / dJK, (t2.y / term1 - (rJK.y - rJI.y * cosTheta) * term2) / dJK, (t2.z / term1 - (rJK.z - rJI.z * cosTheta) * term2) / dJK}; double tg4[3] = {(t3.x / term1 - rJL.x * sinChi / cosChi) / dJL, (t3.y / term1 - rJL.y * sinChi / cosChi) / dJL, (t3.z / term1 - rJL.z * sinChi / cosChi) / dJL}; for (unsigned int i = 0; i < 3; ++i) { g1[i] += dE_dChi * tg1[i]; g2[i] += -dE_dChi * (tg1[i] + tg3[i] + tg4[i]); g3[i] += dE_dChi * tg3[i]; g4[i] += dE_dChi * tg4[i]; } }
bool comparePts(const RDGeom::Point3D &pt1, const RDGeom::Point3D &pt2, double tol=1.0e-4) { RDGeom::Point3D tpt = pt1; tpt -= pt2; return (tpt.length() < tol); }