/* * Atom iterators * * (c) 2014 Schrodinger, Inc. */ #ifndef _H_ATOMITERATORS #define _H_ATOMITERATORS #include "PyMOLGlobals.h" #include "ObjectMolecule.h" #include "CoordSet.h" #include "AtomInfo.h" /** * Atom iterator base class * * The initial state of the iterator points "before" the first atom, there is no * current atom until next() is called the first time. */ class AbstractAtomIterator { protected: int atm; //!< Current atom index in object molecule int idx = -1; //!< Current coordinate index (atom index in coordset) public: ObjectMolecule* obj; //!< Current object molecule CoordSet* cs = nullptr; //!< Current coordiante set // virtual destructor for dynamic types virtual ~AbstractAtomIterator() = default; /// Resets the internal state to start over virtual void reset() = 0; /// Advance the internal state to the next atom. /// @return False if there is no next atom virtual bool next() = 0; /// Current atom AtomInfoType * getAtomInfo() { return obj->AtomInfo + atm; }; const AtomInfoType * getAtomInfo() const { return obj->AtomInfo + atm; }; /// Current atom's coordinates float * getCoord() { return cs->coordPtr(idx); }; /// Current atom index in object molecule int getAtm() const { return atm; } /// Current coordinate index (atom index in coordset) int getIdx() const { return idx; } }; /** * State specific iterator over an atom selection. Similar to `cmd.iterate_state`. * If state is -1 then iterate over all states. * * @verbatim SeleCoordIterator iter(G, sele, state); while(iter.next()) { dump3f(iter.getCoord(), "coords"); } @endverbatim */ class SeleCoordIterator : public AbstractAtomIterator { PyMOLGlobals* G = nullptr; int statearg; // state argument, can be -1 (all), -2 (current), -3 (effective) int statemax; // largest state in selection bool per_object; // whether to iterate over object states or global states ObjectMolecule * prev_obj; // for per_object=true int sele = -1; public: int a; //!< index in selection int state; //!< current state /// Undefined state until copy assigned from a valid state SeleCoordIterator() = default; SeleCoordIterator( PyMOLGlobals* G_, int sele_, int state_, bool update_table = true); void reset(); bool next(); /// Return true if iterating over all states bool isMultistate() const { return statearg == -1; } /// Return true if iterating over all states of an object before advancing /// to the next object, rather than iterating over global states bool isPerObject() const { return per_object; } /// @see isPerObject() void setPerObject(bool per_object_) { per_object = per_object_ && isMultistate(); } private: bool nextStateInPrevObject() { if (prev_obj && (++state) < prev_obj->NCSet) { a = prev_obj->SeleBase - 1; return true; } return false; } }; /** * Iterator over an atom selection. Similar to `cmd.iterate`. * * Does NOT provide coord or coordset access * * @verbatim SeleAtomIterator iter(G, sele); while(iter.next()) { ai = iter.getAtomInfo(); } @endverbatim */ class SeleAtomIterator : public AbstractAtomIterator { PyMOLGlobals * G; int sele; // selection char * stmp; // temporary named selection public: int a; //!< index in selection /// Iterate over an existing atom selection /// @pre ::SelectorUpdateTable was called SeleAtomIterator(PyMOLGlobals * G_, int sele_) { G = G_; sele = sele_; stmp = NULL; reset(); }; SeleAtomIterator(PyMOLGlobals * G_, const char * sele_); ~SeleAtomIterator(); void reset(); bool next(); }; /** * CoordSet atom iterator, iterates over sorted atoms * * @verbatim CoordSetAtomIterator iter(G, cs); while(iter.next()) { dump3f(iter.getCoord(), "coords"); } @endverbatim */ class CoordSetAtomIterator : public AbstractAtomIterator { public: CoordSetAtomIterator(CoordSet * cs_) { cs = cs_; obj = cs->Obj; reset(); } void reset() { atm = -1; } bool next(); }; #endif // vi:sw=2:expandtab