1 /******************************************************************************
2 
3   This source file is part of the Avogadro project.
4 
5   Copyright 2011-2012 Kitware, Inc.
6 
7   This source code is released under the New BSD License, (the "License").
8 
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14 
15 ******************************************************************************/
16 
17 #ifndef AVOGADRO_CORE_ATOM_H
18 #define AVOGADRO_CORE_ATOM_H
19 
20 #include "avogadrocore.h"
21 #include "vector.h"
22 
23 namespace Avogadro {
24 namespace Core {
25 
26 enum AtomHybridization
27 {
28   PerceivedOctaheadral = -6,
29   PerceivedTrigonalBipyramidal = -5,
30   PerceivedSquarePlanar = -4,
31   PerceivedSP3 = -3,
32   PerceivedSP2 = -2,
33   PerceivedSP = -1,
34   HybridizationUnknown = 0,
35   SP = 1,
36   SP2 = 2,
37   SP3 = 3,
38   SquarePlanar = 4,
39   TrigonalBipyramidal = 5,
40   Octahedral = 6
41 };
42 
43 /**
44  * @class Atom atom.h <avogadro/core/atom.h>
45  * The atom class represents an atom in a molecule.
46  * To use the appropriate atom implementation for a specific molecule
47  * implementation, use the [MoleculeClass]::AtomType typedef.
48  */
49 template <class Molecule_T>
50 class AtomTemplate
51 {
52 public:
53   typedef Molecule_T MoleculeType;
54 
55   /** Creates a new, invalid atom object. */
56   AtomTemplate();
57 
58   /**
59    * Creates a new atom object representing the atom at index @p i in molecule
60    * @p m.
61    */
62   AtomTemplate(MoleculeType* m, Index i);
63 
64   /**
65    * @return True if @a this and @a other share the same index and molecule.
66    */
67   bool operator==(const AtomTemplate<MoleculeType>& other) const;
68 
69   /**
70    * @return True if @a this and @a other do not share the same index or
71    * molecule.
72    */
73   bool operator!=(const AtomTemplate<MoleculeType>& other) const;
74 
75   /**
76    * Prefix increment operator. Increment this Atom's index by 1 and return a
77    * self-reference. Check isValid() before calling any other methods.
78    */
79   AtomTemplate<MoleculeType>& operator++();
80 
81   /**
82    * Postfix increment operator. Increment this Atom's index by 1 and return a
83    * copy of the current Atom. Check isValid() before calling any other methods.
84    */
85   AtomTemplate<MoleculeType> operator++(int);
86 
87   /**
88    * Prefix decrement operator. Decrement this Atom's index by 1 and return a
89    * self-reference. Check isValid() before calling any other methods.
90    */
91   AtomTemplate<MoleculeType>& operator--();
92 
93   /**
94    * Postfix decrement operator. Decrement this Atom's index by 1 and return a
95    * copy of the current Atom. Check isValid() before calling any other methods.
96    */
97   AtomTemplate<MoleculeType> operator--(int);
98 
99   /**
100    * @return True if the molecule is set and the index is less than the number
101    * of atoms.
102    */
103   bool isValid() const;
104 
105   /**
106    * @return The molecule that contains this Atom.
107    */
108   MoleculeType* molecule() const;
109 
110   /**
111    * @return The index of this atom in molecule().
112    */
113   Index index() const;
114 
115   /**
116    * The proton count of the atom.
117    * @{
118    */
119   void setAtomicNumber(unsigned char num);
120   unsigned char atomicNumber() const;
121   /** @} */
122 
123   /**
124    * The 2D position of this atom.
125    * @note Not all molecule types support 2D positions. If the current
126    * MoleculeType class does not, calling this method will result in a
127    * compilation error.
128    * @{
129    */
130   void setPosition2d(const Vector2& pos);
131   Vector2 position2d() const;
132   /** @} */
133 
134   /**
135    * The 3D position of this atom.
136    * @{
137    */
138   void setPosition3d(const Vector3& pos);
139   Vector3 position3d() const;
140   /** @} */
141 
142   /**
143    * The hybridization / coordination of this atom
144    * @{
145    */
146   void setHybridization(AtomHybridization hyb);
147   AtomHybridization hybridization() const;
148   /** @} */
149 
150   /**
151    * The formal charge of this atom
152    * @{
153    */
154   void setFormalCharge(signed char charge);
155   signed char formalCharge() const;
156   /** @} */
157 
158   /**
159    * The color of this atom
160    * @{
161    */
162   void setColor(Vector3ub color);
163   Vector3ub color() const;
164   /** @} */
165 
166   /**
167    * Is the atom selected.
168    * {@
169    */
170   void setSelected(bool selected);
171   bool selected() const;
172   /** @} */
173 
174   /**
175    * The force on this atom.
176    * {@
177    */
178   void setForceVector(const Vector3& force);
179   Vector3 forceVector() const;
180   /** @} */
181 
182 private:
183   MoleculeType* m_molecule;
184   Index m_index;
185 };
186 
187 template <class Molecule_T>
AtomTemplate()188 AtomTemplate<Molecule_T>::AtomTemplate()
189   : m_molecule(nullptr), m_index(MaxIndex)
190 {}
191 
192 template <class Molecule_T>
AtomTemplate(MoleculeType * m,Index i)193 AtomTemplate<Molecule_T>::AtomTemplate(MoleculeType* m, Index i)
194   : m_molecule(m), m_index(i)
195 {}
196 
197 template <class Molecule_T>
198 bool AtomTemplate<Molecule_T>::operator==(
199   const AtomTemplate<MoleculeType>& other) const
200 {
201   return m_molecule == other.m_molecule && m_index == other.m_index;
202 }
203 
204 template <class Molecule_T>
205 bool AtomTemplate<Molecule_T>::operator!=(
206   const AtomTemplate<MoleculeType>& other) const
207 {
208   return m_molecule != other.m_molecule || m_index != other.m_index;
209 }
210 
211 template <class Molecule_T>
212 AtomTemplate<Molecule_T>& AtomTemplate<Molecule_T>::operator++()
213 {
214   ++m_index;
215   return *this;
216 }
217 
218 template <class Molecule_T>
219 AtomTemplate<Molecule_T> AtomTemplate<Molecule_T>::operator++(int)
220 {
221   AtomTemplate<MoleculeType> result(m_molecule, m_index++);
222   return result;
223 }
224 
225 template <class Molecule_T>
226 AtomTemplate<Molecule_T>& AtomTemplate<Molecule_T>::operator--()
227 {
228   --m_index;
229   return *this;
230 }
231 
232 template <class Molecule_T>
233 AtomTemplate<Molecule_T> AtomTemplate<Molecule_T>::operator--(int)
234 {
235   AtomTemplate<MoleculeType> result(m_molecule, m_index--);
236   return result;
237 }
238 
239 template <class Molecule_T>
isValid()240 bool AtomTemplate<Molecule_T>::isValid() const
241 {
242   return m_molecule && m_index < m_molecule->atomCount();
243 }
244 
245 template <class Molecule_T>
246 typename AtomTemplate<Molecule_T>::MoleculeType*
molecule()247 AtomTemplate<Molecule_T>::molecule() const
248 {
249   return m_molecule;
250 }
251 
252 template <class Molecule_T>
index()253 Index AtomTemplate<Molecule_T>::index() const
254 {
255   return m_index;
256 }
257 
258 template <class Molecule_T>
setAtomicNumber(unsigned char num)259 void AtomTemplate<Molecule_T>::setAtomicNumber(unsigned char num)
260 {
261   m_molecule->setAtomicNumber(m_index, num);
262 }
263 
264 template <class Molecule_T>
atomicNumber()265 unsigned char AtomTemplate<Molecule_T>::atomicNumber() const
266 {
267   return m_molecule->atomicNumber(m_index);
268 }
269 
270 template <class Molecule_T>
setPosition2d(const Vector2 & pos)271 void AtomTemplate<Molecule_T>::setPosition2d(const Vector2& pos)
272 {
273   m_molecule->setAtomPosition2d(m_index, pos);
274 }
275 
276 template <class Molecule_T>
position2d()277 Vector2 AtomTemplate<Molecule_T>::position2d() const
278 {
279   return m_molecule->atomPositions2d().size() > 0
280            ? m_molecule->atomPositions2d()[m_index]
281            : Vector2::Zero();
282 }
283 
284 template <class Molecule_T>
setPosition3d(const Vector3 & pos)285 void AtomTemplate<Molecule_T>::setPosition3d(const Vector3& pos)
286 {
287   m_molecule->setAtomPosition3d(m_index, pos);
288 }
289 
290 template <class Molecule_T>
position3d()291 Vector3 AtomTemplate<Molecule_T>::position3d() const
292 {
293   return m_molecule->atomPositions3d().size() > 0
294            ? m_molecule->atomPositions3d()[m_index]
295            : Vector3::Zero();
296 }
297 
298 template <class Molecule_T>
setHybridization(AtomHybridization hyb)299 void AtomTemplate<Molecule_T>::setHybridization(AtomHybridization hyb)
300 {
301   m_molecule->setHybridization(m_index, hyb);
302 }
303 
304 template <class Molecule_T>
hybridization()305 AtomHybridization AtomTemplate<Molecule_T>::hybridization() const
306 {
307   return m_molecule->hybridization(m_index);
308 }
309 
310 template <class Molecule_T>
setFormalCharge(signed char charge)311 void AtomTemplate<Molecule_T>::setFormalCharge(signed char charge)
312 {
313   m_molecule->setFormalCharge(m_index, charge);
314 }
315 
316 template <class Molecule_T>
formalCharge()317 signed char AtomTemplate<Molecule_T>::formalCharge() const
318 {
319   return m_molecule->formalCharge(m_index);
320 }
321 
322 template <class Molecule_T>
setColor(Vector3ub color)323 void AtomTemplate<Molecule_T>::setColor(Vector3ub color)
324 {
325   m_molecule->setColor(m_index, std::move(color));
326 }
327 
328 template <class Molecule_T>
color()329 Vector3ub AtomTemplate<Molecule_T>::color() const
330 {
331   return m_molecule->color(m_index);
332 }
333 
334 template <class Molecule_T>
setSelected(bool selected)335 void AtomTemplate<Molecule_T>::setSelected(bool selected)
336 {
337   m_molecule->setAtomSelected(m_index, selected);
338 }
339 
340 template <class Molecule_T>
selected()341 bool AtomTemplate<Molecule_T>::selected() const
342 {
343   return m_molecule->atomSelected(m_index);
344 }
345 
346 template <class Molecule_T>
setForceVector(const Vector3 & force)347 void AtomTemplate<Molecule_T>::setForceVector(const Vector3& force)
348 {
349   m_molecule->setForceVector(m_index, force);
350 }
351 
352 template <class Molecule_T>
forceVector()353 Vector3 AtomTemplate<Molecule_T>::forceVector() const
354 {
355   return m_molecule->forceVectors().size() > 0
356            ? m_molecule->forceVectors()[m_index]
357            : Vector3::Zero();
358 }
359 
360 } // namespace Core
361 } // namespace Avogadro
362 
363 #endif // AVOGADRO_CORE_ATOM_H
364