mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
215 lines
4.5 KiB
C++
215 lines
4.5 KiB
C++
/*
|
|
* Atom iterators
|
|
*
|
|
* (c) 2014 Schrodinger, Inc.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
#include "AtomIterators.h"
|
|
#include "Selector.h"
|
|
#include "SelectorDef.h"
|
|
#include "ObjectMolecule.h"
|
|
#include "CoordSet.h"
|
|
#include "AtomInfo.h"
|
|
|
|
|
|
/*========================================================================*/
|
|
bool CoordSetAtomIterator::next() {
|
|
for (++atm; atm < obj->NAtom; ++atm) {
|
|
idx = cs->atmToIdx(atm);
|
|
|
|
if(idx < 0)
|
|
continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*========================================================================*/
|
|
/**
|
|
* Make a new (owned) atom selection and update the global selector table for it.
|
|
*/
|
|
SeleAtomIterator::SeleAtomIterator(PyMOLGlobals * G_, const char * sele_) {
|
|
G = G_;
|
|
|
|
stmp = new char[1024];
|
|
SelectorGetTmp(G, (char*) sele_, stmp);
|
|
sele = SelectorIndexByName(G, stmp);
|
|
|
|
SelectorUpdateTable(G, cSelectorUpdateTableAllStates, -1);
|
|
|
|
reset();
|
|
}
|
|
|
|
SeleAtomIterator::~SeleAtomIterator() {
|
|
if (stmp) {
|
|
SelectorFreeTmp(G, stmp);
|
|
delete[] stmp;
|
|
}
|
|
}
|
|
|
|
void SeleAtomIterator::reset() {
|
|
a = cNDummyAtoms - 1;
|
|
}
|
|
|
|
/**
|
|
* advance the internal state to the next atom, return false if there is no
|
|
* next atom
|
|
*/
|
|
bool SeleAtomIterator::next() {
|
|
CSelector *I = G->Selector;
|
|
|
|
while ((++a) < I->Table.size()) {
|
|
atm = I->Table[a].atom;
|
|
obj = I->Obj[I->Table[a].model];
|
|
|
|
if(!SelectorIsMember(G, obj->AtomInfo[atm].selEntry, sele))
|
|
continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*========================================================================*/
|
|
/**
|
|
* @param sele_ Atom selection to iterate over
|
|
* @param state_ Object state to iterate over (can be current (-2) or all (-1))
|
|
* @param update_table If true, then update the table (once) and do not call
|
|
* `SelectorIsMember` during iteration, assuming that the table stays valid and
|
|
* contains exactly the selected atoms. If false, then assume the table is
|
|
* up-to-date with a selection different to `sele_` (e.g. with all atoms) and
|
|
* ::SelectorIsMember needs to be called during iteration.
|
|
*/
|
|
SeleCoordIterator::SeleCoordIterator(
|
|
PyMOLGlobals* G_, int sele_, int state_, bool update_table)
|
|
{
|
|
G = G_;
|
|
statearg = state_;
|
|
|
|
// current state (use -3 for "effective" state)
|
|
if (statearg == cStateCurrent) {
|
|
statearg = SettingGetGlobal_i(G, cSetting_state) - 1;
|
|
}
|
|
|
|
// safety check
|
|
if (statearg < cStateAll) {
|
|
statearg = cSelectorUpdateTableEffectiveStates;
|
|
}
|
|
|
|
if (update_table) {
|
|
SelectorUpdateTable(G, statearg, sele_);
|
|
} else {
|
|
sele = sele_;
|
|
}
|
|
|
|
setPerObject(false);
|
|
reset();
|
|
}
|
|
|
|
void SeleCoordIterator::reset() {
|
|
a = cNDummyAtoms - 1;
|
|
state = statearg;
|
|
prev_obj = nullptr;
|
|
cs = nullptr;
|
|
|
|
if (isMultistate()) {
|
|
state = 0;
|
|
statemax = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* advance the internal state to the next atom, return false if there is no
|
|
* next atom
|
|
*/
|
|
bool SeleCoordIterator::next() {
|
|
CSelector *I = G->Selector;
|
|
|
|
for (a++; a < I->Table.size(); a++) {
|
|
obj = I->Obj[I->Table[a].model];
|
|
|
|
if (isMultistate()) {
|
|
if (isPerObject()) {
|
|
if (obj != prev_obj) {
|
|
if (nextStateInPrevObject())
|
|
continue;
|
|
|
|
// first cs of next object
|
|
prev_obj = obj;
|
|
state = 0;
|
|
}
|
|
} else if(statemax < obj->NCSet) {
|
|
statemax = obj->NCSet;
|
|
}
|
|
} else if (statearg == cSelectorUpdateTableEffectiveStates &&
|
|
obj != prev_obj) {
|
|
// "effective" state (no support here for settings all_states=1 or state=0)
|
|
state = std::max(0, obj->getCurrentState());
|
|
prev_obj = obj;
|
|
}
|
|
|
|
if(state >= obj->NCSet || !(cs = obj->CSet[state]))
|
|
continue;
|
|
|
|
atm = I->Table[a].atom;
|
|
idx = cs->atmToIdx(atm);
|
|
|
|
if(idx < 0)
|
|
continue;
|
|
|
|
if (sele > 0 && !SelectorIsMember(G, getAtomInfo()->selEntry, sele))
|
|
continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
if (isMultistate()) {
|
|
if (isPerObject()) {
|
|
if (nextStateInPrevObject())
|
|
return next();
|
|
} else if ((++state) < statemax) {
|
|
a = cNDummyAtoms - 1;
|
|
return next();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
AtomInfoType* AbstractAtomIterator::getAtomInfo()
|
|
{
|
|
return obj->AtomInfo + atm;
|
|
};
|
|
|
|
const AtomInfoType* AbstractAtomIterator::getAtomInfo() const
|
|
{
|
|
return obj->AtomInfo + atm;
|
|
};
|
|
|
|
float* AbstractAtomIterator::getCoord()
|
|
{
|
|
return cs->coordPtr(idx);
|
|
};
|
|
|
|
CoordSetAtomIterator::CoordSetAtomIterator(CoordSet* cs_)
|
|
{
|
|
cs = cs_;
|
|
obj = cs->Obj;
|
|
reset();
|
|
}
|
|
|
|
bool SeleCoordIterator::nextStateInPrevObject() {
|
|
if (prev_obj && (++state) < prev_obj->NCSet) {
|
|
a = prev_obj->SeleBase - 1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// vi:sw=2:expandtab
|