1 /***************************************************************************
2  *   Copyright (C) 2007 by Harm van Eersel                                 *
3  *   devsciurus@xs4all.nl                                                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20 
21 /** @file
22  * This file is part of molsKetch and contains the bond class.
23  *
24  * @author Harm van Eersel <devsciurus@xs4all.nl>
25  * @since Hydrogen
26  */
27 
28 #ifndef BOND_H
29 #define BOND_H
30 
31 #include "atom.h"
32 #include "graphicsitem.h"
33 
34 
35 namespace Molsketch {
36 
37   /**
38  * Represents a bond.
39  *
40  * @author Harm van Eersel
41  */
42   class Bond : public graphicsItem
43   {
44     friend class Molecule;
45 
46   public:
47     enum { Type = graphicsItem::BondType };
type()48     int type() const override {return Type; }
49 
50     enum BondType
51     {
52       Invalid = 0,
53       DativeDot = 1,
54       DativeDash = 2,
55       Single = 10,
56       Wedge  = 11,
57       Hash   = 12,
58       WedgeOrHash = 13,
59       DoubleLegacy = 20,
60       CisOrTrans = 21,
61       DoubleAsymmetric = 22,
62       DoubleSymmetric = 23,
63       Triple = 30,
64       TripleAsymmetric = 31, // TODO more?
65     };
66 
67     static int orderFromType(const BondType& type);
68     static BondType simpleTypeFromOrder(const int& order);
69 
70     /**
71          * Constructor. Create a new bond between @p atomA and @p atomB.
72          *
73          * @param atomA the origin atom of the bond
74          * @param atomB the target atom of the bond
75          * @param order the bond order (@c Bond::Single for single, @c Bond::Double for double, @c Bond::Triple for tripple)
76          * @param type the bond type (@c Bond::Normal, @c Bond::Up, @c Bond::Down, e.g.)
77          */
78     explicit Bond(Atom* atomA = 0, // TODO check usage
79                   Atom* atomB = 0,
80                   Bond::BondType type = Single,
81                   QGraphicsItem* parent = 0) ;
82     explicit Bond(const Bond& other, Atom *atomA = 0, Atom *atomB = 0);
83 
84     virtual ~Bond();
85 
86     void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
87     QVariant itemChange(GraphicsItemChange change, const QVariant & value) override;
88 
89     virtual QPainterPath shape() const override;
90     virtual QRectF boundingRect() const override;
91     /** Returns the angle of this bond from atom @p origin */
92     qreal bondAngle(const Atom* origin) const ;
93     /** Returns the main bond axis */
94     QLineF bondAxis() const ;
95 
96     void setType(const Bond::BondType& type);
97     int bondOrder() const;
98     Bond::BondType bondType() const;
99     Atom* beginAtom() const;
100     Atom* endAtom() const;
101     bool hasAtom(const Atom* atom) const;
102 
103     Atom* otherAtom(const Atom *atom) const;
104     void setAtoms(Atom* A, Atom* B) ;
105     void setAtoms(const QPair<Atom*, Atom*>& atoms);
106     QPair<Atom*, Atom*> atoms() const;
107 
108     Molecule* molecule() const;
109 
110     /**
111          * Auxillary method for shifting a bond perpendicular to the original bond.
112          * Needed for the drawing of multiple bonds.
113          *
114          * @param vector the original vector that is to be shifted
115          * @param shift the amount of shifting
116          *
117          * @return the shifted vector
118          */
119     static QLineF shiftVector(const QLineF & vector, qreal shift);
120 
121     QString xmlName() const override;
122     static QString xmlClassName();
123     /** set the coordinates of the two atoms */
124     void setCoordinates(const QVector<QPointF> &c) override;
125     /** get the coordinates of the two atoms */
126     QPolygonF coordinates() const override;
127 
128   protected:
129     QXmlStreamAttributes graphicAttributes() const override;
130     void readGraphicAttributes(const QXmlStreamAttributes &attributes) override;
131     void prepareContextMenu(QMenu *contextMenu) override;
132     XmlObjectInterface* produceChild(const QString &name, const QXmlStreamAttributes &attributes) override;
133     void afterReadFinalization() override;
134     virtual QPainterPath outline() const;
135 
136   private:
137     QPainterPath drawHashBond() const;
138     QPainterPath drawWedgeBond() const;
139     QPainterPath getWedgeBondShape() const;
140     void determineDoubleBondOrientation();
141     QPainterPath bondPath() const;
142     QPointF determineBondDrawingStart(Atom* start, Atom* end) const;
143     QList<Bond*> coveringBonds() const;
144 
145     // Internal representation
146     Bond::BondType m_bondType;
147     Atom* m_beginAtom;
148     Atom* m_endAtom;
149     QList<XmlObjectInterface*> helpers;
150     QLineF mapOuterLineToAtom(const Atom *atom, const QLineF &line, bool reverse) const;
151     qreal getExtentForStereoBond(const Atom *atom, const QPair<QLineF, QLineF> &outerLines, bool reverse) const;
152     QPair<QLineF, QLineF> getOuterLimitsOfStereoBond() const;
153     qreal bondShapeGap() const;
154     void paintBrokenBondIndicators(QPainter *painter, const QPointF &begin, const QPointF &end, const QPointF &vb, const QPointF &normalVector);
155     QPainterPath getBrokenBondIndicatorsPath(const QPointF &begin, const QPointF &end, const QPointF &normalVector) const;
156     QPainterPath clipBrokenBondIndicator(const QPointF &point, const QPointF &otherAtom, const QPointF &normalVector) const;
157   };
158 
159 } // namespace
160 
161 #endif
162