1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestAppendMolecule.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkDataSetAttributes.h"
17 #include "vtkDoubleArray.h"
18 #include "vtkMolecule.h"
19 #include "vtkMoleculeAppend.h"
20 #include "vtkNew.h"
21 #include "vtkUnsignedCharArray.h"
22 #include "vtkUnsignedShortArray.h"
23
24 #define CheckNumbers(name, first, second) \
25 if (first != second) \
26 { \
27 cerr << "Error : wrong number of " << #name << ". Got " << first << " but expects " << second \
28 << endl; \
29 return EXIT_FAILURE; \
30 }
31
32 // Used to creates different atoms and data for each molecule
33 static int NB_OF_MOL = 0;
34
35 // Add two atoms with a bond between them.
InitSimpleMolecule(vtkMolecule * molecule)36 void InitSimpleMolecule(vtkMolecule* molecule)
37 {
38 NB_OF_MOL++;
39 vtkAtom h1 = molecule->AppendAtom(1, 0.5, 1.5, -NB_OF_MOL);
40 vtkAtom h2 = molecule->AppendAtom(1, 0.5, 1.5, NB_OF_MOL);
41 molecule->AppendBond(h1, h2, 1);
42 }
43
AddAtomData(vtkMolecule * molecule,vtkIdType size)44 void AddAtomData(vtkMolecule* molecule, vtkIdType size)
45 {
46 vtkNew<vtkDoubleArray> data;
47 data->SetName("Data");
48 data->SetNumberOfComponents(1);
49 for (vtkIdType i = 0; i < size; i++)
50 {
51 data->InsertNextValue(NB_OF_MOL * 1.01);
52 }
53 molecule->GetAtomData()->AddArray(data);
54 }
55
CheckMolecule(vtkMolecule * molecule,int nbAtoms,int nbBonds,int nbArrays,vtkDoubleArray * values,int nbGhostAtoms,int nbGhostBonds)56 int CheckMolecule(vtkMolecule* molecule,
57 int nbAtoms,
58 int nbBonds,
59 int nbArrays,
60 vtkDoubleArray* values,
61 int nbGhostAtoms,
62 int nbGhostBonds)
63 {
64 CheckNumbers("atoms", molecule->GetNumberOfAtoms(), nbAtoms);
65 CheckNumbers("bonds", molecule->GetNumberOfBonds(), nbBonds);
66 CheckNumbers("atom data arrays", molecule->GetAtomData()->GetNumberOfArrays(), nbArrays);
67
68 vtkDataArray* resultData = molecule->GetAtomData()->GetArray("Data");
69 if (!resultData)
70 {
71 std::cerr << "Error : atoms data array not found in result" << std::endl;
72 return EXIT_FAILURE;
73 }
74 CheckNumbers("atom data array values", resultData->GetNumberOfTuples(), nbAtoms);
75
76 for (vtkIdType i = 0; i < nbAtoms; i++)
77 {
78 CheckNumbers("data value", resultData->GetTuple1(i), values->GetValue(i));
79 }
80
81 vtkUnsignedShortArray* bondOrderArray = molecule->GetBondOrdersArray();
82 if (!bondOrderArray)
83 {
84 std::cerr << "Error : bonds data array not found in result" << std::endl;
85 return EXIT_FAILURE;
86 }
87 CheckNumbers("bond data array values", bondOrderArray->GetNumberOfTuples(), nbBonds);
88
89 vtkUnsignedCharArray* ghostAtoms = molecule->GetAtomGhostArray();
90 int nbOfGhosts = 0;
91 for (vtkIdType id = 0; id < nbAtoms; id++)
92 {
93 if (ghostAtoms->GetValue(id) == 1)
94 {
95 nbOfGhosts++;
96 }
97 }
98 // ghost atom from molecule2 is still ghost in result
99 CheckNumbers("ghost atoms", nbOfGhosts, nbGhostAtoms);
100
101 vtkUnsignedCharArray* ghostBonds = molecule->GetBondGhostArray();
102 nbOfGhosts = 0;
103 for (vtkIdType id = 0; id < nbBonds; id++)
104 {
105 if (ghostBonds->GetValue(id) == 1)
106 {
107 nbOfGhosts++;
108 }
109 }
110 // ghost bond from molecule2 is still ghost in result
111 CheckNumbers("ghost bonds", nbOfGhosts, nbGhostBonds);
112
113 return EXIT_SUCCESS;
114 }
115
TestAppendMolecule(int,char * [])116 int TestAppendMolecule(int, char* [])
117 {
118 // --------------------------------------------------------------------------
119 // Simple test : 2 molecules, no data
120 vtkNew<vtkMolecule> simpleMolecule1;
121 InitSimpleMolecule(simpleMolecule1);
122
123 vtkNew<vtkMolecule> simpleMolecule2;
124 InitSimpleMolecule(simpleMolecule2);
125
126 vtkNew<vtkMoleculeAppend> appender;
127 appender->AddInputData(simpleMolecule1);
128 appender->AddInputData(simpleMolecule2);
129 appender->Update();
130 vtkMolecule* resultMolecule = appender->GetOutput();
131
132 int expectedResult = simpleMolecule1->GetNumberOfAtoms() + simpleMolecule2->GetNumberOfAtoms();
133 CheckNumbers("atoms", resultMolecule->GetNumberOfAtoms(), expectedResult);
134
135 expectedResult = simpleMolecule1->GetNumberOfBonds() + simpleMolecule2->GetNumberOfBonds();
136 CheckNumbers("bonds", resultMolecule->GetNumberOfBonds(), expectedResult);
137
138 // --------------------------------------------------------------------------
139 // Full test : ghosts and data
140
141 /**
142 * Use 3 molecules:
143 * - fullMolecule1 : 2 atoms and one bond, no ghost
144 * - fullMolecule2 : 3 atoms and 2 bonds, one ghost atom and one ghost bond
145 * - fullMolecule3 : 3 atoms and 2 bonds, one ghost atom and one ghost bond
146 */
147
148 // INIT
149 vtkNew<vtkMolecule> fullMolecule1;
150 InitSimpleMolecule(fullMolecule1);
151 AddAtomData(fullMolecule1, 2);
152 vtkNew<vtkMolecule> fullMolecule2;
153 InitSimpleMolecule(fullMolecule2);
154 AddAtomData(fullMolecule2, 3);
155 vtkNew<vtkMolecule> fullMolecule3;
156 InitSimpleMolecule(fullMolecule3);
157 AddAtomData(fullMolecule3, 3);
158
159 // duplicate first atom of molecule 2 to be ghost in molecule 3, and vice versa.
160 vtkAtom firstAtom2 = fullMolecule2->GetAtom(0);
161 vtkAtom firstAtom3 = fullMolecule3->GetAtom(0);
162
163 vtkAtom ghostAtom2 =
164 fullMolecule2->AppendAtom(firstAtom3.GetAtomicNumber(), firstAtom3.GetPosition());
165 vtkBond ghostBond2 = fullMolecule2->AppendBond(firstAtom2, ghostAtom2, 1);
166
167 vtkAtom ghostAtom3 =
168 fullMolecule3->AppendAtom(firstAtom2.GetAtomicNumber(), firstAtom2.GetPosition());
169 vtkBond ghostBond3 = fullMolecule3->AppendBond(firstAtom3, ghostAtom3, 1);
170
171 // set ghost flag on relevant atoms and bonds.
172 fullMolecule1->AllocateAtomGhostArray();
173 fullMolecule1->AllocateBondGhostArray();
174
175 fullMolecule2->AllocateAtomGhostArray();
176 fullMolecule2->GetAtomGhostArray()->SetValue(ghostAtom2.GetId(), 1);
177 fullMolecule2->AllocateBondGhostArray();
178 fullMolecule2->GetBondGhostArray()->SetValue(ghostBond2.GetId(), 1);
179
180 fullMolecule3->AllocateAtomGhostArray();
181 fullMolecule3->GetAtomGhostArray()->SetValue(ghostAtom3.GetId(), 1);
182 fullMolecule3->AllocateBondGhostArray();
183 fullMolecule3->GetBondGhostArray()->SetValue(ghostBond3.GetId(), 1);
184
185 // --------------------------------------------------------------------------
186 // First part: 2 molecules, ghost and data
187
188 // APPEND 1 with 2
189 vtkNew<vtkMoleculeAppend> appender2;
190 appender2->AddInputData(fullMolecule1);
191 appender2->AddInputData(fullMolecule2);
192 appender2->Update();
193 vtkMolecule* resultFullMolecule = appender2->GetOutput();
194
195 // CHECK RESULT
196 int nbOfExpectedAtoms = fullMolecule1->GetNumberOfAtoms() + fullMolecule2->GetNumberOfAtoms();
197 int nbOfExpectedBonds = fullMolecule1->GetNumberOfBonds() + fullMolecule2->GetNumberOfBonds();
198 int nbOfExpectedArrays = fullMolecule1->GetAtomData()->GetNumberOfArrays();
199 vtkNew<vtkDoubleArray> expectedResultValues;
200 expectedResultValues->InsertNextValue(
201 fullMolecule1->GetAtomData()->GetArray("Data")->GetTuple1(0));
202 expectedResultValues->InsertNextValue(
203 fullMolecule1->GetAtomData()->GetArray("Data")->GetTuple1(1));
204 expectedResultValues->InsertNextValue(
205 fullMolecule2->GetAtomData()->GetArray("Data")->GetTuple1(0));
206 expectedResultValues->InsertNextValue(
207 fullMolecule2->GetAtomData()->GetArray("Data")->GetTuple1(1));
208 expectedResultValues->InsertNextValue(
209 fullMolecule2->GetAtomData()->GetArray("Data")->GetTuple1(2));
210
211 int res = CheckMolecule(resultFullMolecule,
212 nbOfExpectedAtoms,
213 nbOfExpectedBonds,
214 nbOfExpectedArrays,
215 expectedResultValues,
216 1,
217 1);
218 if (res == EXIT_FAILURE)
219 {
220 return EXIT_FAILURE;
221 }
222
223 // --------------------------------------------------------------------------
224 // Second part: 3 molecules, ghost and data, no merge
225 // APPEND third molecule
226 appender2->MergeCoincidentAtomsOff();
227 appender2->AddInputData(fullMolecule3);
228 appender2->Update();
229 resultFullMolecule = appender2->GetOutput();
230
231 // CHECK RESULT
232 nbOfExpectedAtoms = fullMolecule1->GetNumberOfAtoms() + fullMolecule2->GetNumberOfAtoms() +
233 fullMolecule3->GetNumberOfAtoms();
234 nbOfExpectedBonds = fullMolecule1->GetNumberOfBonds() + fullMolecule2->GetNumberOfBonds() +
235 fullMolecule3->GetNumberOfBonds();
236 nbOfExpectedArrays = fullMolecule1->GetAtomData()->GetNumberOfArrays();
237
238 // Result contains data of non ghost atom.
239 expectedResultValues->InsertNextValue(
240 fullMolecule3->GetAtomData()->GetArray("Data")->GetTuple1(0));
241 expectedResultValues->InsertNextValue(
242 fullMolecule3->GetAtomData()->GetArray("Data")->GetTuple1(1));
243 expectedResultValues->InsertNextValue(
244 fullMolecule3->GetAtomData()->GetArray("Data")->GetTuple1(2));
245
246 res = CheckMolecule(resultFullMolecule,
247 nbOfExpectedAtoms,
248 nbOfExpectedBonds,
249 nbOfExpectedArrays,
250 expectedResultValues,
251 2,
252 2);
253 if (res == EXIT_FAILURE)
254 {
255 return EXIT_FAILURE;
256 }
257
258 // --------------------------------------------------------------------------
259 // Third part: 3 molecules, ghost and data, merge coincident atoms
260
261 appender2->MergeCoincidentAtomsOn();
262 appender2->Update();
263 resultFullMolecule = appender2->GetOutput();
264 // the ghost atoms are not duplicated in output.
265 nbOfExpectedAtoms = fullMolecule1->GetNumberOfAtoms() + fullMolecule2->GetNumberOfAtoms() +
266 fullMolecule3->GetNumberOfAtoms() - 2;
267 // the ghost bond is not duplicated in output.
268 nbOfExpectedBonds = fullMolecule1->GetNumberOfBonds() + fullMolecule2->GetNumberOfBonds() +
269 fullMolecule3->GetNumberOfBonds() - 1;
270 expectedResultValues->Resize(nbOfExpectedAtoms);
271 expectedResultValues->InsertValue(
272 4, fullMolecule3->GetAtomData()->GetArray("Data")->GetTuple1(0));
273 expectedResultValues->InsertValue(
274 4, fullMolecule3->GetAtomData()->GetArray("Data")->GetTuple1(1));
275
276 return CheckMolecule(resultFullMolecule,
277 nbOfExpectedAtoms,
278 nbOfExpectedBonds,
279 nbOfExpectedArrays,
280 expectedResultValues,
281 0,
282 0);
283 }
284