void NeighborList::initOneTwo() { unsigned int numAtoms = m_atoms.size(); if (!numAtoms) return; m_oneTwo.resize(m_atoms.size()); m_oneThree.resize(m_atoms.size()); if (m_atoms.isEmpty()) return; Molecule *molecule = m_atoms.first()->molecule(); if (!molecule) { qDebug() << "Error, null molecule returned in NeighborList::initOneTwo()"; return; } foreach (Atom *atom, m_atoms) { foreach (unsigned long id1, atom->neighbors()) { Atom *nbr1 = molecule->atomById(id1); m_oneTwo[atom->index()].push_back(nbr1->index()); m_oneTwo[nbr1->index()].push_back(atom->index()); foreach (unsigned long id2, nbr1->neighbors()) { Atom *nbr2 = molecule->atomById(id2); if (atom->index() == nbr2->index()) continue; m_oneThree[atom->index()].push_back(nbr2->index()); m_oneThree[nbr2->index()].push_back(atom->index()); } } }
bool RingEngine::renderRing(const QList<unsigned long> &ring, PainterDevice *pd) { // We need to get rid of the constness in order to get the atoms Molecule *mol = const_cast<Molecule *>(pd->molecule()); // Calculate an appropriate normal and use it for all the triangles in the // ring - this will give consistent lighting. Eigen::Vector3d v1, v2, norm; v1 = *mol->atomById(ring[1])->pos() - *mol->atomById(ring[0])->pos(); v2 = *mol->atomById(ring[2])->pos() - *mol->atomById(ring[1])->pos(); norm = v1.cross(v2); if (norm.dot(pd->camera()->backTransformedZAxis()) > 0) norm *= -1; // Disable face culling for ring structures. glDisable(GL_CULL_FACE); // Optimize for smaller ring structures switch (ring.size()) { case 3: // Single triangle - easy pd->painter()->setColor(ringColors[0][0], ringColors[0][1], ringColors[0][2], m_alpha); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[1])->pos(), *mol->atomById(ring[2])->pos(), norm); break; case 4: // Two triangles pd->painter()->setColor(ringColors[1][0], ringColors[1][1], ringColors[1][2], m_alpha); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[1])->pos(), *mol->atomById(ring[2])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[2])->pos(), *mol->atomById(ring[3])->pos(), norm); break; case 5: // Three triangles pd->painter()->setColor(ringColors[2][0], ringColors[2][1], ringColors[2][2], m_alpha); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[1])->pos(), *mol->atomById(ring[2])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[2])->pos(), *mol->atomById(ring[3])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[3])->pos(), *mol->atomById(ring[4])->pos(), norm); break; case 6: // Four triangles pd->painter()->setColor(ringColors[3][0], ringColors[3][1], ringColors[3][2], m_alpha); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[1])->pos(), *mol->atomById(ring[2])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[2])->pos(), *mol->atomById(ring[3])->pos(), *mol->atomById(ring[4])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[4])->pos(), *mol->atomById(ring[5])->pos(), *mol->atomById(ring[0])->pos(), norm); pd->painter()->drawTriangle(*mol->atomById(ring[0])->pos(), *mol->atomById(ring[2])->pos(), *mol->atomById(ring[4])->pos(), norm); break; default: // The generic case - find the centre of the ring and draw a triangle fan pd->painter()->setColor(ringColors[4][0], ringColors[4][1], ringColors[4][2], m_alpha); Vector3d center; for (int i = 0; i < ring.size(); i++) center += *mol->atomById(ring[i])->pos(); center /= ring.size(); for (int i = 0; i < ring.size()-1; i++) pd->painter()->drawTriangle(center, *mol->atomById(ring[i])->pos(), *mol->atomById(ring[i+1])->pos(), norm); pd->painter()->drawTriangle(center, *mol->atomById(ring[ring.size()-1])->pos(), *mol->atomById(ring[0])->pos(), norm); } return true; }