1 /******************************************************************************
2
3 This source file is part of the Avogadro project.
4
5 Copyright 2013-2015 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_QTGUI_RWMOLECULE_H
18 #define AVOGADRO_QTGUI_RWMOLECULE_H
19
20 #include "avogadroqtguiexport.h"
21 #include <QtCore/QObject>
22
23 #include "molecule.h"
24 #include "persistentatom.h"
25 #include "persistentbond.h"
26
27 #include <avogadro/core/array.h>
28 #include <avogadro/core/atom.h>
29 #include <avogadro/core/avogadrocore.h>
30 #include <avogadro/core/bond.h>
31 #include <avogadro/core/crystaltools.h>
32 #include <avogadro/core/unitcell.h>
33 #include <avogadro/core/vector.h>
34
35 #include <QtWidgets/QUndoStack>
36
37 namespace Avogadro {
38 namespace QtGui {
39
40 /** Concrete atom/bond proxy classes for RWMolecule. @{ */
41 class RWAtom;
42 class RWBond;
43 /** @} */
44
45 /**
46 * @class RWMolecule rwmolecule.h <avogadro/qtgui/rwmolecule.h>
47 * @brief The RWMolecule class is an editable molecule class that automatically
48 * populates an undo stack.
49 *
50 * This class implements the molecule API and composes a QUndoStack
51 * (undoStack()). New undo commands are automatically generated and push each
52 * time a non-const method is called.
53 *
54 * An interactive mode is supported that causes "noisy" commands, such as
55 * atom position changes, to be merged into a single command, saving memory
56 * keeping the stack usable during interactive editing of the molecule. Use
57 * setInteractive(bool) to toggle interactive mode.
58 *
59 * Similarly, multiple sequences of commands can be compressed into a single
60 * named action using the QUndoStack's macro capability. Call
61 * undoStack().beginMacro(tr("User Description Of Change")) to begin a macro,
62 * and undoStack().endMacro() when finished.
63 */
64 class AVOGADROQTGUI_EXPORT RWMolecule : public QObject
65 {
66 Q_OBJECT
67
68 public:
69 /** Typedef for Atom class. */
70 typedef RWAtom AtomType;
71
72 /** Typedef for PersistentAtom class. */
73 typedef PersistentAtom<RWMolecule> PersistentAtomType;
74
75 /** Typedef for Bond class. */
76 typedef RWBond BondType;
77
78 /** Typedef for PersistentBond class. */
79 typedef PersistentBond<RWMolecule> PersistentBondType;
80
81 /** Construct a molecule with the atoms/bonds of mol. */
82 explicit RWMolecule(Molecule& mol, QObject* parent = 0);
83
84 ~RWMolecule() override;
85
molecule()86 Molecule& molecule() { return m_molecule; }
molecule()87 const Molecule& molecule() const { return m_molecule; }
88
89 /**
90 * Add a new atom to the molecule.
91 * @param atomicNumber The atomic number of the new atom.
92 * @param usingPositions Whether or not to use positions for this atom.
93 * Default is true. Set to false if the atom
94 * will not be using coordinates.
95 * @return The new Atom object.
96 */
97 AtomType addAtom(unsigned char atomicNumber, bool usingPositions = true);
98
99 /**
100 * Add a new atom to the molecule and set its position.
101 * @param atomicNumber The atomic number of the new atom.
102 * @param position3d The position of the atom.
103 * @return The new Atom object.
104 */
105 AtomType addAtom(unsigned char atomicNumber, const Vector3& position3d);
106
107 /**
108 * Obtain an atom object.
109 * @param atomId The index of the atom to return.
110 * @return The requested atom object. Will be invalid if @a atomId >= @a
111 * atomCount().
112 */
113 AtomType atom(Index atomId) const;
114
115 /**
116 * Obtain an atom object from it's unique id.
117 * @param atomUId The unique of the requested atom.
118 * @return The requested atom object. Will be invalid if @a atomUId is not
119 * in use.
120 */
121 AtomType atomByUniqueId(Index atomUId) const;
122
123 /**
124 * @return The unique id of the atom.
125 * @{
126 */
127 Index atomUniqueId(Index atomId) const;
128 Index atomUniqueId(const AtomType& atom) const;
129 /** @} */
130
131 /**
132 * @return The number of atoms in the molecule.
133 */
134 Index atomCount() const;
135
136 /**
137 * @return The number of atoms in the molecule with the atomic number @a
138 * atomicNumber.
139 */
140 Index atomCount(unsigned char atomicNumber) const;
141
142 /**
143 * Delete the specified atom from this molecule.
144 * @return True on success, false otherwise.
145 * @note This also removes all bonds connected to the atom.
146 * @{
147 */
148 bool removeAtom(Index atomId);
149 bool removeAtom(const AtomType& atom);
150 /** @} */
151
152 /**
153 * Delete all atoms from this molecule.
154 * @note This also removes all bonds.
155 */
156 void clearAtoms();
157
158 /**
159 * Adjust hydrogens for an atom.
160 * @param atomId The index of the atom.
161 * @note Checks to make sure the atom is valid before adjusting the hydrogens.
162 */
163 void adjustHydrogens(Index atomId);
164
165 /**
166 * Adjust hydrogens for multiple atoms.
167 * @param atomIds The indices for the atoms.
168 * @note Checks to make sure the atoms are valid before adjusting the
169 * hydrogens.
170 */
171 void adjustHydrogens(const Core::Array<Index>& atomIds);
172
173 /**
174 * @return An array containing atomic numbers for all atoms in the molecule,
175 * indexed by atom index.
176 */
177 const Core::Array<unsigned char>& atomicNumbers() const;
178
179 /**
180 * Get the atomic number for the requested atom.
181 * @param atomId The index of the atom.
182 * @return The atomic number of the atom indexed at @a atomId, or
183 * Avogadro::InvalidElement if @a atomId is invalid.
184 */
185 unsigned char atomicNumber(Index atomId) const;
186
187 /**
188 * Replace the current array of atomic numbers.
189 * @param nums The new atomic number array. Must be of length atomCount().
190 * @return True on success, false otherwise.
191 */
192 bool setAtomicNumbers(const Core::Array<unsigned char>& nums);
193
194 /**
195 * Set the atomic number of a single atom.
196 * @param atomId The index of the atom to modify.
197 * @param atomicNumber The new atomic number.
198 * @return True on success, false otherwise.
199 */
200 bool setAtomicNumber(Index atomId, unsigned char atomicNumber);
201
202 /**
203 * @return An array containing 3D coordinates for all atoms in the molecule,
204 * indexed by atom index.
205 * @note May be empty if position information has not been set for any atoms.
206 */
207 const Core::Array<Vector3>& atomPositions3d() const;
208
209 /**
210 * Get the 3D position of a single atom.
211 * @param atomId The index of the atom.
212 * @return The position of the atom, or Vector3::Zero() if no position
213 * information has been set.
214 */
215 Vector3 atomPosition3d(Index atomId) const;
216
217 /**
218 * Replace the current array of 3D atomic coordinates.
219 * @param pos The new coordinate array. Must be of length atomCount().
220 * @param undoText The undo text to be displayed for undo commands.
221 * @return True on success, false otherwise.
222 */
223 bool setAtomPositions3d(
224 const Core::Array<Vector3>& pos,
225 const QString& undoText = QStringLiteral("Change Atom Positions"));
226
227 /**
228 * Set the 3D position of a single atom.
229 * @param atomId The index of the atom to modify.
230 * @param pos The new position of the atom.
231 * @param undoText The undo text to be displayed for undo commands.
232 * @return True on success, false otherwise.
233 */
234 bool setAtomPosition3d(
235 Index atomId, const Vector3& pos,
236 const QString& undoText = QStringLiteral("Change Atom Position"));
237
238 /**
239 * Set whether the specified atom is selected or not.
240 */
241 void setAtomSelected(Index atomId, bool selected);
242
243 /**
244 * Query whether the supplied atom index has been selected.
245 */
246 bool atomSelected(Index atomId) const;
247
setAtomPosition2d(Index,const Vector2 &)248 bool setAtomPosition2d(Index, const Vector2&) { return false; }
atomPosition2d(Index)249 Vector2 atomPosition2d(Index) { return Vector2(0, 0); }
atomPositions2d()250 const Core::Array<Vector2>& atomPositions2d() const
251 {
252 return m_molecule.m_positions2d;
253 }
254
255 /**
256 * Get the hybridization for the requested atom.
257 * @param atomId The index of the atom.
258 * @return The hybridization of the atom indexed at @a atomId, or
259 * 0 if @a atomId is invalid.
260 */
261 Core::AtomHybridization hybridization(Index atomId) const;
262
263 /**
264 * Set the hybridization of a single atom.
265 * @param atomId The index of the atom to modify.
266 * @param hyb The new hybridization.
267 * @return True on success, false otherwise.
268 */
269 bool setHybridization(Index atomId, Core::AtomHybridization hyb);
270
271 /**
272 * Get the formal charge for the requested atom.
273 * @param atomId The index of the atom.
274 * @return The formal charge of the atom indexed at @a atomId, or
275 * 0 if @a atomId is invalid.
276 */
277 signed char formalCharge(Index atomId) const;
278
279 /**
280 * Set the formal charge of a single atom.
281 * @param atomId The index of the atom to modify.
282 * @param charge The new formal charge.
283 * @return True on success, false otherwise.
284 */
285 bool setFormalCharge(Index atomId, signed char charge);
286
287 /**
288 * Get the color for the requested atom.
289 * @param atomId The index of the atom.
290 * @return The color of the atom indexed at @a atomId, or
291 * (0, 0, 0) if @a atomId is invalid. If no color is set for the
292 * given atomId, the default color for the atomic number of
293 * the atomId is returned.
294 */
295 Vector3ub color(Index atomId) const;
296
297 /**
298 * Set the color of a single atom.
299 * @param atomId The index of the atom to modify.
300 * @param color The new color.
301 * @return True on success, false otherwise.
302 */
303 bool setColor(Index atomId, Vector3ub color);
304
305 /**
306 * Create a new bond in the molecule.
307 * @param atom1 The first atom in the bond.
308 * @param atom2 The second order in the bond.
309 * @param order The bond order.
310 * @return The new bond object. Will be invalid if @a atom1 or @a atom2 does
311 * not exist.
312 * @{
313 */
314 BondType addBond(Index atom1, Index atom2, unsigned char order = 1);
315 BondType addBond(const AtomType& atom1, const AtomType& atom2,
316 unsigned char order = 1);
317 /** @} */
318
319 /**
320 * Get a bond object.
321 * @param bondId The index of the requested bond.
322 * @return The requested bond object. Will be invalid if @a bondId >=
323 * @a bondCount().
324 */
325 BondType bond(Index bondId) const;
326
327 /**
328 * Get a bond object.
329 * @param atom1 The index of one atom in the bond.
330 * @param atom2 The index of the other atom in bond.
331 * @return The requested bond object. Will be invalid if @a atom1 or @a atom2
332 * do not exist.
333 */
334 BondType bond(Index atom1, Index atom2) const;
335
336 /**
337 * Get a bond object.
338 * @param atom1 One atom in the bond.
339 * @param atom2 The other atom in bond.
340 * @return The requested bond object. Will be invalid if @a atom1 or @a atom2
341 * are invalid.
342 */
343 BondType bond(const AtomType& atom1, const AtomType& atom2) const;
344
345 /**
346 * Get a bond object from its unique id.
347 * @param bondUid The unique id of the bond.
348 * @return The requested bond object. Will be invalid if @a bondUid is not in
349 * use.
350 */
351 BondType bondByUniqueId(Index bondUid) const;
352
353 /**
354 * Get the unique id of a bond.
355 * @param bondId The index of the requested bond.
356 * @return The unique id currently assigned to the bond at index @a bondId
357 */
358 Index bondUniqueId(Index bondId) const;
359
360 /**
361 * Get the unique id of a bond.
362 * @param bond The requested bond object.
363 * @return The unique id currently assigned to @a bond.
364 */
365 Index bondUniqueId(const BondType& bond) const;
366
367 /**
368 * @return The number of bonds in the molecule.
369 */
370 Index bondCount() const;
371
372 /**
373 * Remove the requested bond.
374 * @return True on success, false otherwise.
375 * @{
376 */
377 bool removeBond(Index bondId);
378 bool removeBond(const BondType& bond);
379 bool removeBond(Index atom1, Index atom2);
380 bool removeBond(const AtomType& atom1, const AtomType& atom2);
381 /** @} */
382
383 /**
384 * Remove all bonds from the molecule.
385 */
386 void clearBonds();
387
388 /**
389 * Find bonds connected to an atom.
390 * @param atom The atom of interest.
391 * @return An array of bond objects that are attached to the specified atom.
392 */
393 Core::Array<BondType> bonds(const AtomType& atom) const;
394
395 /**
396 * Find bonds connected to an atom.
397 * @param atomId The index for the atom of interest.
398 * @return An array of bond objects that are attached to the specified atom.
399 */
400 Core::Array<BondType> bonds(const Index& atomId) const;
401
402 /**
403 * @return An array of bond orders for all bonds in the molecule, indexed by
404 * bond index.
405 */
406 const Core::Array<unsigned char>& bondOrders() const;
407
408 /**
409 * Get the order of a bond.
410 * @param bondId The id of the bond.
411 * @return The bond order.
412 */
413 unsigned char bondOrder(Index bondId) const;
414
415 /**
416 * Replace the current array of bond orders.
417 * @param orders The new array.
418 * @return True on success, false on failure.
419 */
420 bool setBondOrders(const Core::Array<unsigned char>& orders);
421
422 /**
423 * Set the order of a bond in the molecule.
424 * @param bondId The bond's index.
425 * @param order The new order of the bond.
426 * @return True on success, false on failure.
427 */
428 bool setBondOrder(Index bondId, unsigned char order);
429
430 /**
431 * @return An array of all bonded atoms in the molecule, indexed by bond
432 * index.
433 * Each bond pair is represented by a pair of atom indices.
434 */
435 const Core::Array<std::pair<Index, Index>>& bondPairs() const;
436
437 /**
438 * Get the set of bonded atoms corresponding to @a bondId.
439 * @param bondId The index of the requested bond.
440 * @return The bonded atom pair, represented as a pair of atom indices.
441 */
442 std::pair<Index, Index> bondPair(Index bondId) const;
443
444 /**
445 * Replace the current array of bonded atoms.
446 * @param pairs The array.
447 * @return True on success, false on failure.
448 * @note The bonded atoms are represented as a pair of bond indices.
449 * @note If needed, the elements in @a pairs will be modified to ensure that
450 * the first atom index is less than the second.
451 */
452 bool setBondPairs(const Core::Array<std::pair<Index, Index>>& pairs);
453
454 /**
455 * Set the bonded atoms for a bond.
456 * @param bondId The bond to modify.
457 * @param pair The new bond pair.
458 * @return True on success, false otherwise.
459 * @note If needed, @a pair will be modified to ensure that the first atom
460 * index is less than the second.
461 */
462 bool setBondPair(Index bondId, const std::pair<Index, Index>& pair);
463
464 /**
465 * Add a default unit cell to the molecule. Does nothing if there already
466 * is a unit cell. Changes are emitted.
467 */
468 void addUnitCell();
469
470 /**
471 * Remove the unit cell from the molecule. Does nothing if there is
472 * no unit cell. Changes are emitted.
473 */
474 void removeUnitCell();
475
476 /**
477 * Generic edit that changes the current molecule to be @a newMolecule.
478 * Also sets the text for the undo command to be @a undoText. Changes are
479 * emitted.
480 * @param newMolecule The new molecule to be set.
481 * @param changes The changes to be emitted.
482 * @param undoText The text description for the undo command.
483 */
484 void modifyMolecule(
485 const Molecule& newMolecule, Molecule::MoleculeChanges changes,
486 const QString& undoText = QStringLiteral("Modify Molecule"));
487
488 /**
489 * Generic edit that adds @a newMolecule to the current molecule.
490 * Also sets the text for the undo command to be @a undoText. Changes are
491 * emitted.
492 * @param addMolecule The new molecule to be set.
493 * @param undoText The text description for the undo command.
494 */
495 void appendMolecule(
496 const Molecule& addMolecule,
497 const QString& undoText = QStringLiteral("Append Molecule"));
498
499 /**
500 * Edit the unit cell by replacing the current cell matrix with a new cell
501 * matrix. Changes are emitted.
502 * @param cellMatrix The new cell matrix to be set.
503 * @param opts If TransformAtoms is specified, the atoms in @a molecule are
504 * adjusted so that their fractional (lattice) coordinates are preserved. This
505 * option is ignored if the input molecule has no unit cell.
506 */
507 void editUnitCell(Matrix3 cellMatrix, Core::CrystalTools::Options opts);
508
509 /**
510 * Wrap atoms to the unit cell. Changes are emitted.
511 */
512 void wrapAtomsToCell();
513
514 /**
515 * Rotate cell to standard orientation. Changes are emitted.
516 */
517 void rotateCellToStandardOrientation();
518
519 /**
520 * Scale a cell's volume. Changes are emitted.
521 * @param newVolume The new volume to be set.
522 * @param options If CrystalTools::TransformAtoms is set, then
523 * the atoms will be transformed during the scaling.
524 */
525 void setCellVolume(double newVolume, Core::CrystalTools::Options options);
526
527 /**
528 * Build a supercell. Changes are emitted.
529 * @param a The final number of units along the A vector (at least 1).
530 * @param b The final number of units along the B vector (at least 1).
531 * @param c The final number of units along the C vector (at least 1).
532 */
533 void buildSupercell(unsigned int a, unsigned int b, unsigned int c);
534
535 /**
536 * Perform a Niggli reduction on the cell. Changes are emitted.
537 */
538 void niggliReduceCell();
539
540 /**
541 * Use spglib to reduce the cell to its primitive form. Changes are emitted.
542 * @param cartTol Cartesian tolerance for primitive reduction.
543 * @return True if the algorithm succeeded, and false if it failed.
544 */
545 bool reduceCellToPrimitive(double cartTol = 1e-5);
546
547 /**
548 * Use spglib to convert the cell to its conventional form. Changes are
549 * emitted.
550 * @param cartTol Cartesian tolerance for conventionalization.
551 * @return True if the algorithm succeeded, and false if it failed.
552 */
553 bool conventionalizeCell(double cartTol = 1e-5);
554
555 /**
556 * Use spglib to symmetrize the cell. Changes are emitted.
557 * @param cartTol Cartesian tolerance for symmetrization.
558 * @return True if the algorithm succeeded, and false if it failed.
559 */
560 bool symmetrizeCell(double cartTol = 1e-5);
561
562 /**
563 * Fill unit cell using transforms for the space group. Changes are emitted.
564 * @param hallNumber The hall number to be used for transforming the cell.
565 * @param cartTol Cartesian tolerance for comparing atom positions.
566 * @return True if the algorithm succeeded, and false if it failed.
567 */
568 bool fillUnitCell(unsigned short hallNumber, double cartTol = 1e-5);
569
570 /**
571 * Use transforms to reduce a cell to its asymmetric unit. Changes are
572 * emitted.
573 * @param hallNumber The hall number to be used for obtaining the transforms.
574 * @param cartTol Cartesian tolerance for comparing atom positions.
575 * @return True if the algorithm succeeded, and false if it failed.
576 */
577 bool reduceCellToAsymmetricUnit(unsigned short hallNumber,
578 double cartTol = 1e-5);
579
580 /**
581 * Call this function when you wish to merge all undo commands.
582 * It turns on interactive mode to merge similar undo commands in a series
583 * (in order to save space), and it uses QUndoStack's beginMacro() to merge
584 * dissimilar undo commands together. You must call endMergeMode() to end
585 * the merging section (undo and redo are unavailable while merge mode is
586 * on).
587 * @param undoName The name of the undo command
588 */
589 void beginMergeMode(const QString& undoName = QStringLiteral("Draw"));
590
591 /**
592 * Call this function when you wish merge mode to end. This will turn off
593 * interactive mode, and it will call QUndoStack's endMacro(). All of the
594 * undo commands pushed between beginMergeMode() and endMergeMode() will be
595 * merged into one undo command. beginMergeMode() should have been called
596 * before this is called.
597 */
598 void endMergeMode();
599
600 /**
601 * @brief Begin or end an interactive edit.
602 *
603 * If enabled, certain undo operations will be merged together. For instance,
604 * an editor dragging an atom through space in response to mouse movement will
605 * only generate a single undo command containing the initial and final
606 * positions and discard the intermediate states. If disabled, each
607 * intermediate action will appear in the undo log.
608 */
609 void setInteractive(bool b);
610
611 /**
612 * @return True if interactive mode is enabled, false otherwise.
613 * @sa setInteractive
614 */
615 bool isInteractive() const;
616
617 /**
618 * @return The QUndoStack for this molecule.
619 * @{
620 */
621 QUndoStack& undoStack();
622 const QUndoStack& undoStack() const;
623 /** @} */
624
625 class UndoCommand;
626 friend class UndoCommand;
627
628 /** Returns a vector of forces for the atoms in the molecule. */
629 const Core::Array<Vector3>& forceVectors() const;
630
631 /**
632 * Replace the current array of force vectors.
633 * @param pos The new force vector array. Must be of length atomCount().
634 * @param undoText The undo text to be displayed for undo commands.
635 * @return True on success, false otherwise.
636 */
637 bool setForceVector(
638 Index atomId, const Vector3& pos,
639 const QString& undoText = QStringLiteral("Change Force Vectors"));
640
641 public slots:
642 /**
643 * @brief Force the molecule to emit the changed() signal.
644 * @param change See changed().
645 */
646 void emitChanged(unsigned int change);
647
648 signals:
649 /**
650 * @brief Indicates that the molecule has changed.
651 * @param change Use the MoleculeChange enum to check what has changed.
652 *
653 * The @p change variable indicates what has changed, i.e. if
654 * change & Atoms == true then atoms were changed in some way, and if
655 * change & Removed == true then one or more atoms were removed.
656 */
657 void changed(unsigned int change);
658
659 protected:
660 Index findAtomUniqueId(Index atomId) const;
661 Index findBondUniqueId(Index bondId) const;
662
663 /**
664 * @brief m_molecule still stored all data, this class acts upon it and builds
665 * an undo/redo stack that can be used to offer undo and redo.
666 */
667 Molecule& m_molecule;
668 bool m_interactive;
669
670 QUndoStack m_undoStack;
671
672 friend class Molecule;
673 };
674
675 class AVOGADROQTGUI_EXPORT RWAtom : public Core::AtomTemplate<RWMolecule>
676 {
677 public:
RWAtom()678 RWAtom() : Core::AtomTemplate<RWMolecule>() {}
RWAtom(RWMolecule * m,Index i)679 RWAtom(RWMolecule* m, Index i) : Core::AtomTemplate<RWMolecule>(m, i) {}
680 };
681
682 class AVOGADROQTGUI_EXPORT RWBond : public Core::BondTemplate<RWMolecule>
683 {
684 public:
RWBond()685 RWBond() : Core::BondTemplate<RWMolecule>() {}
RWBond(RWMolecule * m,Index i)686 RWBond(RWMolecule* m, Index i) : Core::BondTemplate<RWMolecule>(m, i) {}
687 };
688
atom(Index atomId)689 inline RWMolecule::AtomType RWMolecule::atom(Index atomId) const
690 {
691 return AtomType(const_cast<RWMolecule*>(this), atomId);
692 }
693
atomByUniqueId(Index atomUId)694 inline RWMolecule::AtomType RWMolecule::atomByUniqueId(Index atomUId) const
695 {
696 return atomUId < m_molecule.m_atomUniqueIds.size()
697 ? AtomType(const_cast<RWMolecule*>(this),
698 m_molecule.m_atomUniqueIds[atomUId])
699 : AtomType();
700 }
701
atomUniqueId(Index atomId)702 inline Index RWMolecule::atomUniqueId(Index atomId) const
703 {
704 return findAtomUniqueId(atomId);
705 }
706
atomUniqueId(const RWMolecule::AtomType & a)707 inline Index RWMolecule::atomUniqueId(const RWMolecule::AtomType& a) const
708 {
709 return a.molecule() == this ? findAtomUniqueId(a.index()) : MaxIndex;
710 }
711
atomCount()712 inline Index RWMolecule::atomCount() const
713 {
714 return m_molecule.atomCount();
715 }
716
removeAtom(const AtomType & a)717 inline bool RWMolecule::removeAtom(const AtomType& a)
718 {
719 return a.molecule() == this ? removeAtom(a.index()) : false;
720 }
721
atomicNumbers()722 inline const Core::Array<unsigned char>& RWMolecule::atomicNumbers() const
723 {
724 return m_molecule.atomicNumbers();
725 }
726
atomicNumber(Index atomId)727 inline unsigned char RWMolecule::atomicNumber(Index atomId) const
728 {
729 return m_molecule.atomicNumber(atomId);
730 }
731
atomPositions3d()732 inline const Core::Array<Vector3>& RWMolecule::atomPositions3d() const
733 {
734 return m_molecule.atomPositions3d();
735 }
736
atomPosition3d(Index atomId)737 inline Vector3 RWMolecule::atomPosition3d(Index atomId) const
738 {
739 return m_molecule.atomPosition3d(atomId);
740 }
741
hybridization(Index atomId)742 inline Core::AtomHybridization RWMolecule::hybridization(Index atomId) const
743 {
744 return m_molecule.hybridization(atomId);
745 }
746
formalCharge(Index atomId)747 inline signed char RWMolecule::formalCharge(Index atomId) const
748 {
749 return m_molecule.formalCharge(atomId);
750 }
751
color(Index atomId)752 inline Vector3ub RWMolecule::color(Index atomId) const
753 {
754 return m_molecule.color(atomId);
755 }
756
addBond(const AtomType & atom1,const AtomType & atom2,unsigned char order)757 inline RWMolecule::BondType RWMolecule::addBond(const AtomType& atom1,
758 const AtomType& atom2,
759 unsigned char order)
760 {
761 if (atom1.molecule() != atom2.molecule() || atom1.molecule() != this)
762 return BondType();
763 return addBond(atom1.index(), atom2.index(), order);
764 }
765
bond(Index bondId)766 inline RWMolecule::BondType RWMolecule::bond(Index bondId) const
767 {
768 return BondType(const_cast<RWMolecule*>(this), bondId);
769 }
770
bond(const RWMolecule::AtomType & atom1,const RWMolecule::AtomType & atom2)771 inline RWMolecule::BondType RWMolecule::bond(
772 const RWMolecule::AtomType& atom1, const RWMolecule::AtomType& atom2) const
773 {
774 if (atom1.molecule() == atom2.molecule() && atom1.molecule() == this)
775 return bond(atom1.index(), atom2.index());
776 return BondType();
777 }
778
bondByUniqueId(Index bondUid)779 inline RWMolecule::BondType RWMolecule::bondByUniqueId(Index bondUid) const
780 {
781 return bondUid < m_molecule.m_bondUniqueIds.size()
782 ? BondType(const_cast<RWMolecule*>(this),
783 m_molecule.m_bondUniqueIds[bondUid])
784 : BondType();
785 }
786
bondUniqueId(Index bondId)787 inline Index RWMolecule::bondUniqueId(Index bondId) const
788 {
789 return findBondUniqueId(bondId);
790 }
791
bondUniqueId(const RWMolecule::BondType & b)792 inline Index RWMolecule::bondUniqueId(const RWMolecule::BondType& b) const
793 {
794 return b.molecule() == this ? findBondUniqueId(b.index()) : MaxIndex;
795 }
796
bondCount()797 inline Index RWMolecule::bondCount() const
798 {
799 return m_molecule.bondCount();
800 }
801
removeBond(const RWMolecule::BondType & b)802 inline bool RWMolecule::removeBond(const RWMolecule::BondType& b)
803 {
804 return b.molecule() == this ? removeBond(b.index()) : false;
805 }
806
removeBond(Index atom1,Index atom2)807 inline bool RWMolecule::removeBond(Index atom1, Index atom2)
808 {
809 return removeBond(bond(atom1, atom2).index());
810 }
811
removeBond(const RWMolecule::AtomType & atom1,const RWMolecule::AtomType & atom2)812 inline bool RWMolecule::removeBond(const RWMolecule::AtomType& atom1,
813 const RWMolecule::AtomType& atom2)
814 {
815 if (atom1.molecule() != atom2.molecule() || atom1.molecule() != this)
816 return false;
817 return removeBond(bond(atom1.index(), atom2.index()).index());
818 }
819
bonds(const RWMolecule::AtomType & a)820 inline Core::Array<RWMolecule::BondType> RWMolecule::bonds(
821 const RWMolecule::AtomType& a) const
822 {
823 return a.molecule() == this ? bonds(a.index()) : Core::Array<BondType>();
824 }
825
bonds(const Index & atomId)826 inline Core::Array<RWMolecule::BondType> RWMolecule::bonds(
827 const Index& atomId) const
828 {
829 Core::Array<RWMolecule::BondType> result;
830 for (Index i = 0; i < m_molecule.m_bondPairs.size(); ++i)
831 if (m_molecule.m_bondPairs[i].first == atomId ||
832 m_molecule.m_bondPairs[i].second == atomId)
833 result.push_back(BondType(const_cast<RWMolecule*>(this), i));
834 return result;
835 }
836
bondOrders()837 inline const Core::Array<unsigned char>& RWMolecule::bondOrders() const
838 {
839 return m_molecule.bondOrders();
840 }
841
bondOrder(Index bondId)842 inline unsigned char RWMolecule::bondOrder(Index bondId) const
843 {
844 return m_molecule.bondOrder(bondId);
845 }
846
bondPairs()847 inline const Core::Array<std::pair<Index, Index>>& RWMolecule::bondPairs() const
848 {
849 return m_molecule.bondPairs();
850 }
851
bondPair(Index bondId)852 inline std::pair<Index, Index> RWMolecule::bondPair(Index bondId) const
853 {
854 return m_molecule.bondPair(bondId);
855 }
856
beginMergeMode(const QString & undoName)857 inline void RWMolecule::beginMergeMode(const QString& undoName)
858 {
859 m_interactive = true;
860 m_undoStack.beginMacro(undoName);
861 }
862
endMergeMode()863 inline void RWMolecule::endMergeMode()
864 {
865 m_interactive = false;
866 m_undoStack.endMacro();
867 }
868
setInteractive(bool b)869 inline void RWMolecule::setInteractive(bool b)
870 {
871 m_interactive = b;
872 }
873
isInteractive()874 inline bool RWMolecule::isInteractive() const
875 {
876 return m_interactive;
877 }
878
undoStack()879 inline QUndoStack& RWMolecule::undoStack()
880 {
881 return m_undoStack;
882 }
883
undoStack()884 inline const QUndoStack& RWMolecule::undoStack() const
885 {
886 return m_undoStack;
887 }
888
forceVectors()889 inline const Core::Array<Vector3>& RWMolecule::forceVectors() const
890 {
891 return m_molecule.forceVectors();
892 }
893
894 } // namespace QtGui
895 } // namespace Avogadro
896
897 #endif // AVOGADRO_QTGUI_RWMOLECULE_H
898