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 #include "utils.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <avogadro/core/array.h>
22 #include <avogadro/core/color3f.h>
23 #include <avogadro/core/mesh.h>
24 #include <avogadro/core/molecule.h>
25 #include <avogadro/core/vector.h>
26 
27 using Avogadro::Index;
28 using Avogadro::Vector2;
29 using Avogadro::Vector3;
30 using Avogadro::Vector3f;
31 using Avogadro::Core::Array;
32 using Avogadro::Core::Atom;
33 using Avogadro::Core::Bond;
34 using Avogadro::Core::Color3f;
35 using Avogadro::Core::Mesh;
36 using Avogadro::Core::Molecule;
37 using Avogadro::Core::Variant;
38 using Avogadro::Core::VariantMap;
39 
40 class MoleculeTest : public testing::Test
41 {
42 public:
43   MoleculeTest();
44 
45 protected:
46   Molecule m_testMolecule;
47 };
48 
MoleculeTest()49 MoleculeTest::MoleculeTest()
50 {
51   Atom o1 = m_testMolecule.addAtom(8);
52   Atom h2 = m_testMolecule.addAtom(1);
53   Atom h3 = m_testMolecule.addAtom(1);
54 
55   o1.setPosition3d(Vector3(0, 0, 0));
56   h2.setPosition3d(Vector3(0.6, -0.5, 0));
57   h3.setPosition3d(Vector3(-0.6, -0.5, 0));
58 
59   o1.setPosition2d(Vector2(0, 0));
60   h2.setPosition2d(Vector2(0.6, -0.5));
61   h3.setPosition2d(Vector2(-0.6, -0.5));
62 
63   // Add some data
64   VariantMap data;
65   data.setValue("test", Variant("test"));
66   m_testMolecule.setDataMap(data);
67 
68   // Add some bonds
69   m_testMolecule.perceiveBondsSimple();
70 
71   Mesh* mesh = m_testMolecule.addMesh();
72 
73   Array<Vector3f> vertices;
74   Array<Vector3f> normals;
75   Array<Color3f> colors;
76 
77   Color3f color = Color3f(23, 23, 23);
78   colors.push_back(color);
79 
80   Vector3f vec(1.2f, 1.3f, 1.4f);
81 
82   vertices.push_back(vec);
83   normals.push_back(vec);
84 
85   mesh->setColors(colors);
86   mesh->setNormals(normals);
87   mesh->setVertices(vertices);
88   mesh->setIsoValue(1.2f);
89   mesh->setName("testmesh");
90   mesh->setOtherMesh(1);
91   mesh->setStable(false);
92 }
93 
TEST_F(MoleculeTest,addAtom)94 TEST_F(MoleculeTest, addAtom)
95 {
96   Molecule molecule;
97   EXPECT_EQ(molecule.atomCount(), static_cast<Index>(0));
98 
99   Avogadro::Core::Atom atom = molecule.addAtom(6);
100   EXPECT_EQ(atom.isValid(), true);
101   EXPECT_EQ(molecule.atomCount(), static_cast<Index>(1));
102   EXPECT_EQ(atom.index(), 0);
103   EXPECT_EQ(atom.atomicNumber(), static_cast<unsigned char>(6));
104 
105   Avogadro::Core::Atom atom2 = molecule.addAtom(1);
106   EXPECT_EQ(atom2.isValid(), true);
107   EXPECT_EQ(molecule.atomCount(), static_cast<Index>(2));
108   EXPECT_EQ(atom2.index(), 1);
109   EXPECT_EQ(atom2.atomicNumber(), static_cast<unsigned char>(1));
110 }
111 
TEST_F(MoleculeTest,removeAtom)112 TEST_F(MoleculeTest, removeAtom)
113 {
114   Molecule molecule;
115   Atom atom0 = molecule.addAtom(6);
116   Atom atom1 = molecule.addAtom(1);
117   Atom atom2 = molecule.addAtom(1);
118   Atom atom3 = molecule.addAtom(1);
119   Atom atom4 = molecule.addAtom(1);
120   molecule.addBond(atom0, atom1, 1);
121   molecule.addBond(atom0, atom2, 1);
122   molecule.addBond(atom0, atom3, 1);
123   molecule.addBond(atom0, atom4, 1);
124 
125   EXPECT_EQ(5, molecule.atomCount());
126   EXPECT_EQ(4, molecule.bondCount());
127 
128   molecule.removeAtom(atom0);
129 
130   EXPECT_EQ(4, molecule.atomCount());
131   EXPECT_EQ(0, molecule.bondCount());
132 
133   molecule.clearAtoms();
134 
135   EXPECT_EQ(0, molecule.atomCount());
136 }
137 
TEST_F(MoleculeTest,addBond)138 TEST_F(MoleculeTest, addBond)
139 {
140   Molecule molecule;
141   EXPECT_EQ(molecule.bondCount(), static_cast<Index>(0));
142 
143   Atom a = molecule.addAtom(1);
144   Atom b = molecule.addAtom(1);
145   Bond bondAB = molecule.addBond(a, b);
146   EXPECT_TRUE(bondAB.isValid());
147   EXPECT_EQ(bondAB.molecule(), &molecule);
148   EXPECT_EQ(molecule.bondCount(), static_cast<Index>(1));
149   EXPECT_EQ(bondAB.index(), static_cast<Index>(0));
150   EXPECT_EQ(bondAB.atom1().index(), a.index());
151   EXPECT_EQ(bondAB.atom2().index(), b.index());
152   EXPECT_EQ(bondAB.order(), static_cast<unsigned char>(1));
153 
154   Atom c = molecule.addAtom(1);
155   Bond bondBC = molecule.addBond(b, c, 2);
156   EXPECT_TRUE(bondBC.isValid());
157   EXPECT_EQ(molecule.bondCount(), static_cast<Index>(2));
158   EXPECT_EQ(bondBC.index(), static_cast<Index>(1));
159   EXPECT_EQ(bondBC.order(), static_cast<unsigned char>(2));
160 
161   // try to lookup nonexistant bond
162   Bond bond = molecule.bond(a, c);
163   EXPECT_FALSE(bond.isValid());
164 
165   // try to lookup bond between a and b
166   bond = molecule.bond(a, b);
167   EXPECT_TRUE(bond.isValid());
168   EXPECT_EQ(bond.molecule(), &molecule);
169   EXPECT_EQ(bond.atom1().index(), a.index());
170   EXPECT_EQ(bond.atom2().index(), b.index());
171 
172   // try to lookup bond between b and c by index
173   bond = molecule.bond(1);
174   EXPECT_TRUE(bond.isValid());
175   EXPECT_EQ(bond.molecule(), &molecule);
176   EXPECT_EQ(bond.atom1().index(), b.index());
177   EXPECT_EQ(bond.atom2().index(), c.index());
178 }
179 
TEST_F(MoleculeTest,removeBond)180 TEST_F(MoleculeTest, removeBond)
181 {
182   Molecule molecule;
183   Atom a = molecule.addAtom(1);
184   Atom b = molecule.addAtom(1);
185   Bond bondAB = molecule.addBond(a, b);
186   Atom c = molecule.addAtom(1);
187   molecule.addBond(b, c, 2);
188 
189   EXPECT_EQ(3, molecule.atomCount());
190   EXPECT_EQ(2, molecule.bondCount());
191   EXPECT_TRUE(molecule.bond(a, b).isValid());
192   EXPECT_TRUE(molecule.bond(b, c).isValid());
193 
194   molecule.removeBond(bondAB);
195 
196   EXPECT_EQ(3, molecule.atomCount());
197   EXPECT_EQ(1, molecule.bondCount());
198   EXPECT_FALSE(molecule.bond(a, b).isValid());
199   EXPECT_TRUE(molecule.bond(b, c).isValid());
200 
201   molecule.clearBonds();
202 
203   EXPECT_EQ(0, molecule.bondCount());
204 }
205 
TEST_F(MoleculeTest,findBond)206 TEST_F(MoleculeTest, findBond)
207 {
208   Molecule molecule;
209   Atom a1 = molecule.addAtom(5);
210   Atom a2 = molecule.addAtom(6);
211   Bond b = molecule.addBond(a1, a2, 1);
212 
213   EXPECT_EQ(molecule.bond(a1, a2).index(), b.index());
214   EXPECT_EQ(molecule.bond(a2, a1).index(), b.index());
215 
216   Array<Bond> bonds = molecule.bonds(a1);
217   EXPECT_EQ(bonds.size(), 1);
218 
219   Atom a3 = molecule.addAtom(7);
220   molecule.addBond(a1, a3, 1);
221   EXPECT_EQ(molecule.bonds(a1).size(), 2);
222   EXPECT_EQ(molecule.bonds(a3).size(), 1);
223 }
224 
TEST_F(MoleculeTest,setData)225 TEST_F(MoleculeTest, setData)
226 {
227   Molecule molecule;
228   molecule.setData("name", "ethanol");
229   EXPECT_EQ(molecule.data("name").toString(), "ethanol");
230 }
231 
TEST_F(MoleculeTest,dataMap)232 TEST_F(MoleculeTest, dataMap)
233 {
234   Molecule molecule;
235   molecule.setData("name", "ethanol");
236   molecule.setData("formula", "C2H6O");
237   VariantMap varMap = molecule.dataMap();
238   varMap.setValue("SMILES", "CCO");
239   molecule.setDataMap(varMap);
240   molecule.dataMap().setValue("CAS", "64-17-5");
241 
242   std::vector<std::string> dataNames = molecule.dataMap().names();
243   EXPECT_EQ(dataNames.size(), 4);
244   EXPECT_EQ(molecule.hasData("name"), true);
245   EXPECT_EQ(molecule.hasData("invalid"), false);
246   EXPECT_EQ(molecule.data("name").toString(), "ethanol");
247   EXPECT_EQ(molecule.data("formula").toString(), "C2H6O");
248   EXPECT_EQ(molecule.data("SMILES").toString(), "CCO");
249   EXPECT_EQ(molecule.data("CAS").toString(), "64-17-5");
250 }
251 
TEST_F(MoleculeTest,perceiveBondsSimple)252 TEST_F(MoleculeTest, perceiveBondsSimple)
253 {
254   Molecule molecule;
255   Atom o1 = molecule.addAtom(8);
256   Atom h2 = molecule.addAtom(1);
257   Atom h3 = molecule.addAtom(1);
258 
259   o1.setPosition3d(Vector3(0, 0, 0));
260   h2.setPosition3d(Vector3(0.6, -0.5, 0));
261   h3.setPosition3d(Vector3(-0.6, -0.5, 0));
262   EXPECT_EQ(molecule.bondCount(), 0);
263 
264   molecule.perceiveBondsSimple();
265   EXPECT_EQ(molecule.bondCount(), 2);
266   EXPECT_TRUE(molecule.bond(o1, h2).isValid());
267   EXPECT_TRUE(molecule.bond(o1, h3).isValid());
268   EXPECT_FALSE(molecule.bond(h2, h3).isValid());
269 }
270 
TEST_F(MoleculeTest,copy)271 TEST_F(MoleculeTest, copy)
272 {
273   Molecule copy(m_testMolecule);
274 
275   assertEqual(m_testMolecule, copy);
276 }
277 
TEST_F(MoleculeTest,assignment)278 TEST_F(MoleculeTest, assignment)
279 {
280   Molecule assign;
281   assign = m_testMolecule;
282 
283   assertEqual(m_testMolecule, assign);
284 }
285