1 /*
2  *  sketcherMinimizerEZConstrainInteraction.h
3  *
4  *  Created by Nicola Zonta
5  *   Copyright Schrodinger, LLC. All rights reserved.
6  *
7  */
8 
9 #ifndef sketcherMINIMIZEREZCONSTRAININTERACTION
10 #define sketcherMINIMIZEREZCONSTRAININTERACTION
11 
12 #include "sketcherMinimizerInteraction.h"
13 
14 /* forcefield constrain to avoid EZ inversion */
15 class sketcherMinimizerEZConstrainInteraction
16     : public sketcherMinimizerInteraction
17 {
18   public:
sketcherMinimizerEZConstrainInteraction(sketcherMinimizerAtom * at1,sketcherMinimizerAtom * at2,sketcherMinimizerAtom * at3,sketcherMinimizerAtom * at4,bool isZ)19     sketcherMinimizerEZConstrainInteraction(sketcherMinimizerAtom* at1,
20                                             sketcherMinimizerAtom* at2,
21                                             sketcherMinimizerAtom* at3,
22                                             sketcherMinimizerAtom* at4,
23                                             bool isZ)
24         : sketcherMinimizerInteraction(at1, at2)
25     {
26         atom3 = at3;
27         atom4 = at4;
28         m_isZ = isZ;
29         m_forceMovement = false;
30     };
31     ~sketcherMinimizerEZConstrainInteraction() override = default;
32 
33     /* calculate the energy of the interaction */
energy(float & e)34     void energy(float& e) override
35     {
36         if (inversion()) {
37             e += 5000;
38         }
39     };
40 
41     /* calculate the forces and apply them */
42     void score(float& totalE, bool = false) override
43     {
44         if (!inversion()) {
45             return;
46         }
47         energy(totalE);
48         sketcherMinimizerPointF projection1 =
49             sketcherMinimizerMaths::projectPointOnLine(
50                 atom1->coordinates, atom2->coordinates, atom3->coordinates);
51         sketcherMinimizerPointF projection2 =
52             sketcherMinimizerMaths::projectPointOnLine(
53                 atom4->coordinates, atom2->coordinates, atom3->coordinates);
54         sketcherMinimizerAtom* sideAtom = atom1;
55         sketcherMinimizerAtom* doubleBondAtom = atom2;
56         sketcherMinimizerPointF projection = projection1;
57         if (sketcherMinimizerMaths::squaredDistance(atom1->coordinates,
58                                                     projection1) >
59             sketcherMinimizerMaths::squaredDistance(atom4->coordinates,
60                                                     projection2)) {
61             sideAtom = atom4;
62             doubleBondAtom = atom3;
63             projection = projection2;
64         }
65         sketcherMinimizerPointF force = projection - sideAtom->coordinates;
66         if (m_forceMovement) {
67             sideAtom->coordinates += force;
68             doubleBondAtom->coordinates -= force;
69             sideAtom->force = sketcherMinimizerPointF(0, 0);
70             doubleBondAtom->force = sketcherMinimizerPointF(0, 0);
71         } else {
72             force.normalize();
73             force *= 10;
74             sideAtom->force += force;
75             doubleBondAtom->force -= force;
76         }
77     };
78 
79     /* check if the E/Z configuration is inverted */
inversion()80     bool inversion()
81     {
82         return sketcherMinimizerMaths::sameSide(
83                    atom1->coordinates, atom4->coordinates, atom2->coordinates,
84                    atom3->coordinates) != m_isZ;
85     }
86     sketcherMinimizerAtom* atom3;
87     sketcherMinimizerAtom* atom4;
88     float k2;
89     bool m_isZ;
90     bool m_forceMovement;
91 };
92 
93 #endif // sketcherMINIMIZEREZCONSTRAININTERACTION
94