This tutorial demonstrates how to use the vlMolecule module classes to manipulate and render molecules and chemical structures.
The vlMolecule module is a simple and minimalistic framework to manipulate and render chemical structures. The vl::Molecule class is the most important member of the module and represents a molecular structure as a collection of vl::Atom[s] and vl::Bond[s]. The vl::Molecule class allows you to add and remove both atoms and bonds in order to create any kind of molecule. The vlMolecule framework is flexible and intuitive, it allows you for example to set the color, the size, the visibility etc. for each atom and for each bond, it allows you to define the geometrical detail for bonds and atoms, it allows you highlight aromatic rings and much more.
The vlMolecule module also provide a comprehensive atom database, in fact using the vl::atomInfo() function the user can retrieve information like element name, element symbol, atom number, electronegativity, cpk color, various radii etc. for a given atom type (vl::EAtomType).
Using the vl::loadMOL2() function you can also load a MOL2 (or multi-MOL2) file.
The example below implements a simple molecule viewer.
|
|
|
|
Wireframe style | Sticks style | Ball & Sticks style | CPK space fill style |
[From App_Molecules.cpp
]
class App_Molecules: public BaseDemo
{
public:
App_Molecules(): mCurrentMolecule(0), mCurrentStyle(0), mText( new
vl::Text ) {}
void updateMolecule()
{
if (mCurrentStyle == 0)
{
mMolecules[mCurrentMolecule]->setCPKAtomColors();
mMolecules[mCurrentMolecule]->setLineWidth(2.0f);
mMolecules[mCurrentMolecule]->setSmoothLines(true);
}
else
if (mCurrentStyle == 1)
{
mMolecules[mCurrentMolecule]->setCPKAtomColors();
mMolecules[mCurrentMolecule]->setAtomRadii(0.30f);
mMolecules[mCurrentMolecule]->setBondRadii(0.15f);
}
else
if (mCurrentStyle == 2)
{
mMolecules[mCurrentMolecule]->setCPKAtomColors();
mMolecules[mCurrentMolecule]->setBondRadii(0.10f);
}
else
if (mCurrentStyle == 3)
{
mMolecules[mCurrentMolecule]->setCPKAtomColors();
mMolecules[mCurrentMolecule]->setVanDerWaalsAtomRadii();
}
mMolecules[mCurrentMolecule]->prepareForRendering();
sceneManager()->tree()->eraseAllChildren();
sceneManager()->tree()->addChild( mMolecules[mCurrentMolecule]->actorTree() );
updateText();
}
void initEvent()
{
mText->setText("Drop a MOL2 file inside the window.");
mText->setFont(
vl::defFontManager()->acquireFont(
"/font/bitstream-vera/VeraMono.ttf", 10) );
mText->translate(0,-5,0);
mText->setColor(vl::white);
sceneManager()->tree()->addActor(mText.get(), effect.
get());
loadMolecule("/mol/molecule.mol2");
}
{
mCurrentMolecule = 0;
if (!mMolecules.empty())
updateMolecule();
trackball()->adjustView( rendering()->as<vl::Rendering>(),
vl::vec3(0,0,1),
vl::vec3(0,1,0), 1.0f );
for(size_t i=0; i<mMolecules.size(); ++i)
{
msg =
"New molecule: " + mMolecules[i]->moleculeName() +
" - " +
vl::String::fromInt(mMolecules[i]->atomCount()) +
" atoms\n";
}
}
void fileDroppedEvent(const std::vector<vl::String>& files)
{
loadMolecule( files[0] );
}
void keyPressEvent(
unsigned short ch,
vl::EKey key)
{
BaseDemo::keyPressEvent(ch,key);
{
if (mCurrentMolecule<0) mCurrentMolecule = (int)mMolecules.size()-1;
if (mCurrentMolecule>(int)mMolecules.size()-1) mCurrentMolecule = 0;
if (mCurrentStyle<0) mCurrentStyle = 3;
if (mCurrentStyle>3) mCurrentStyle = 0;
updateMolecule();
}
}
void updateText()
{
vl::String msg = mMolecules[mCurrentMolecule]->moleculeName();
msg +=
vl::Say(
" (%n/%n)") << mCurrentMolecule+1 << mMolecules.size();
if (mCurrentStyle == 0)
msg += " - Wireframe";
if (mCurrentStyle == 1)
msg += " - Ball & Stick";
if (mCurrentStyle == 2)
msg += " - Sticks";
if (mCurrentStyle == 3)
msg += " - CPK";
msg += "\nuse the arrow keys to change molecule and style";
mText->setText(msg);
}
protected:
std::vector< vl::ref<vl::Molecule> > mMolecules;
int mCurrentMolecule;
int mCurrentStyle;
};