1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkMolecule.h 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 * @class vtkMolecule 17 * @brief class describing a molecule 18 * 19 * 20 * 21 * vtkMolecule and the convenience classes vtkAtom and vtkBond 22 * describe the geometry and connectivity of a molecule. The molecule 23 * can be constructed using the AppendAtom() and AppendBond() methods in one 24 * of two ways; either by fully specifying the atom/bond in a single 25 * call, or by incrementally setting the various attributes using the 26 * convenience vtkAtom and vtkBond classes: 27 * 28 * Single call: 29 * \code 30 * vtkMolecule *mol = vtkMolecule::New(); 31 * vtkAtom h1 = mol->AppendAtom(1, 0.0, 0.0, -0.5); 32 * vtkAtom h2 = mol->AppendAtom(1, 0.0, 0.0, 0.5); 33 * vtkBond b = mol->AppendBond(h1, h2, 1); 34 * \endcode 35 * 36 * Incremental: 37 * \code 38 * vtkMolecule *mol = vtkMolecule::New(); 39 * 40 * vtkAtom h1 = mol->AppendAtom(); 41 * h1.SetAtomicNumber(1); 42 * h1.SetPosition(0.0, 0.0, -0.5); 43 * 44 * vtkAtom h2 = mol->AppendAtom(); 45 * h2.SetAtomicNumber(1); 46 * vtkVector3d displacement (0.0, 0.0, 1.0); 47 * h2.SetPosition(h1.GetPositionAsVector3d() + displacement); 48 * 49 * vtkBond b = mol->AppendBond(h1, h2, 1); 50 * \endcode 51 * 52 * Both of the above methods will produce the same molecule, two 53 * hydrogens connected with a 1.0 Angstrom single bond, aligned to the 54 * z-axis. The second example also demonstrates the use of VTK's 55 * vtkVector class, which is fully supported by the Chemistry kit. 56 * 57 * The vtkMolecule object is intended to be used with the 58 * vtkMoleculeMapper class for visualizing molecular structure using 59 * common rendering techniques. 60 * 61 * \warning While direct use of the underlying vtkUndirectedGraph 62 * structure is possible due to vtkMolecule's public inheritance, this 63 * should not be relied upon and may change in the future. 64 * 65 * @sa 66 * vtkAtom vtkBond vtkMoleculeMapper vtkPeriodicTable 67 */ 68 69 #ifndef vtkMolecule_h 70 #define vtkMolecule_h 71 72 #include "vtkCommonDataModelModule.h" // For export macro 73 #include "vtkSmartPointer.h" // For vtkSmartPointer 74 #include "vtkUndirectedGraph.h" 75 76 #include "vtkAtom.h" // Simple proxy class dependent on vtkMolecule 77 #include "vtkBond.h" // Simple proxy class dependent on vtkMolecule 78 79 #include "vtkVector.h" // Small templated vector convenience class 80 81 class vtkAbstractElectronicData; 82 class vtkDataArray; 83 class vtkInformation; 84 class vtkInformationVector; 85 class vtkMatrix3x3; 86 class vtkPlane; 87 class vtkPoints; 88 class vtkUnsignedCharArray; 89 class vtkUnsignedShortArray; 90 91 class VTKCOMMONDATAMODEL_EXPORT vtkMolecule : public vtkUndirectedGraph 92 { 93 public: 94 static vtkMolecule* New(); 95 vtkTypeMacro(vtkMolecule, vtkUndirectedGraph); 96 void PrintSelf(ostream& os, vtkIndent indent) override; 97 void Initialize() override; 98 99 /** 100 * Return what type of dataset this is. 101 */ GetDataObjectType()102 int GetDataObjectType() override { return VTK_MOLECULE; } 103 104 /** 105 * Add new atom with atomic number 0 (dummy atom) at origin. Return 106 * a vtkAtom that refers to the new atom. 107 */ AppendAtom()108 vtkAtom AppendAtom() { return this->AppendAtom(0, 0., 0., 0.); } 109 110 ///@{ 111 /** 112 * Add new atom with the specified atomic number and position. Return a 113 * vtkAtom that refers to the new atom. 114 */ 115 vtkAtom AppendAtom(unsigned short atomicNumber, double x, double y, double z); AppendAtom(unsigned short atomicNumber,const vtkVector3f & pos)116 vtkAtom AppendAtom(unsigned short atomicNumber, const vtkVector3f& pos) 117 { 118 return this->AppendAtom(atomicNumber, pos[0], pos[1], pos[2]); 119 } 120 AppendAtom(unsigned short atomicNumber,double pos[3])121 vtkAtom AppendAtom(unsigned short atomicNumber, double pos[3]) 122 { 123 return this->AppendAtom(atomicNumber, pos[0], pos[1], pos[2]); 124 } 125 ///@} 126 127 /** 128 * Return a vtkAtom that refers to the atom with the specified id. 129 */ 130 vtkAtom GetAtom(vtkIdType atomId); 131 132 /** 133 * Return the number of atoms in the molecule. 134 */ 135 vtkIdType GetNumberOfAtoms(); 136 137 ///@{ 138 /** 139 * Add a bond between the specified atoms, optionally setting the 140 * bond order (default: 1). Return a vtkBond object referring to the 141 * new bond. 142 */ 143 vtkBond AppendBond(vtkIdType atom1, vtkIdType atom2, unsigned short order = 1); 144 vtkBond AppendBond(const vtkAtom& atom1, const vtkAtom& atom2, unsigned short order = 1) 145 { 146 return this->AppendBond(atom1.Id, atom2.Id, order); 147 } 148 ///@} 149 150 /** 151 * Return a vtkAtom that refers to the bond with the specified id. 152 */ 153 vtkBond GetBond(vtkIdType bondId); 154 155 /** 156 * Return the number of bonds in the molecule. 157 */ 158 vtkIdType GetNumberOfBonds(); 159 160 /** 161 * Return the atomic number of the atom with the specified id. 162 */ 163 unsigned short GetAtomAtomicNumber(vtkIdType atomId); 164 165 /** 166 * Set the atomic number of the atom with the specified id. 167 */ 168 void SetAtomAtomicNumber(vtkIdType atomId, unsigned short atomicNum); 169 170 ///@{ 171 /** 172 * Set the position of the atom with the specified id. 173 */ 174 void SetAtomPosition(vtkIdType atomId, const vtkVector3f& pos); 175 void SetAtomPosition(vtkIdType atomId, double x, double y, double z); SetAtomPosition(vtkIdType atomId,double pos[3])176 void SetAtomPosition(vtkIdType atomId, double pos[3]) 177 { 178 this->SetAtomPosition(atomId, pos[0], pos[1], pos[2]); 179 } 180 ///@} 181 182 ///@{ 183 /** 184 * Get the position of the atom with the specified id. 185 */ 186 vtkVector3f GetAtomPosition(vtkIdType atomId); 187 void GetAtomPosition(vtkIdType atomId, float pos[3]); 188 void GetAtomPosition(vtkIdType atomId, double pos[3]); 189 ///@} 190 191 ///@{ 192 /** 193 * Get/Set the bond order of the bond with the specified id 194 */ 195 void SetBondOrder(vtkIdType bondId, unsigned short order); 196 unsigned short GetBondOrder(vtkIdType bondId); 197 ///@} 198 199 /** 200 * Get the bond length of the bond with the specified id 201 202 * \note If the associated vtkBond object is already available, 203 * vtkBond::GetBondLength is potentially much faster than this 204 * function, as a list of all bonds may need to be constructed to 205 * locate the appropriate bond. 206 * \sa UpdateBondList() 207 */ 208 double GetBondLength(vtkIdType bondId); 209 210 ///@{ 211 /** 212 * Access the raw arrays used in this vtkMolecule instance 213 */ 214 vtkPoints* GetAtomicPositionArray(); 215 vtkUnsignedShortArray* GetAtomicNumberArray(); 216 vtkUnsignedShortArray* GetBondOrdersArray(); 217 ///@} 218 219 ///@{ 220 /** 221 * Set/Get the AbstractElectronicData-subclassed object for this molecule. 222 */ 223 vtkGetObjectMacro(ElectronicData, vtkAbstractElectronicData); 224 virtual void SetElectronicData(vtkAbstractElectronicData*); 225 ///@} 226 227 /** 228 * Performs the same operation as ShallowCopy(), 229 * but instead of reporting an error for an incompatible graph, 230 * returns false. 231 */ 232 bool CheckedShallowCopy(vtkGraph* g) override; 233 234 /** 235 * Performs the same operation as DeepCopy(), 236 * but instead of reporting an error for an incompatible graph, 237 * returns false. 238 */ 239 bool CheckedDeepCopy(vtkGraph* g) override; 240 241 /** 242 * Shallow copies the data object into this molecule. 243 */ 244 void ShallowCopy(vtkDataObject* obj) override; 245 246 /** 247 * Deep copies the data object into this molecule. 248 */ 249 void DeepCopy(vtkDataObject* obj) override; 250 251 /** 252 * Shallow copies the atoms and bonds from @a m into @a this. 253 */ 254 virtual void ShallowCopyStructure(vtkMolecule* m); 255 256 /** 257 * Deep copies the atoms and bonds from @a m into @a this. 258 */ 259 virtual void DeepCopyStructure(vtkMolecule* m); 260 261 /** 262 * Shallow copies attributes (i.e. everything besides atoms and bonds) from 263 * @a m into @a this. 264 */ 265 virtual void ShallowCopyAttributes(vtkMolecule* m); 266 267 /** 268 * Deep copies attributes (i.e. everything besides atoms and bonds) from 269 * @a m into @a this. 270 */ 271 virtual void DeepCopyAttributes(vtkMolecule* m); 272 273 ///@{ 274 /** 275 * Obtain the plane that passes through the indicated bond with the given 276 * normal. If the plane is set successfully, the function returns true. 277 278 * If the normal is not orthogonal to the bond, a new normal will be 279 * constructed in such a way that the plane will be orthogonal to 280 * the plane spanned by the bond vector and the input normal vector. 281 282 * This ensures that the plane passes through the bond, and the 283 * normal is more of a "hint" indicating the orientation of the plane. 284 285 * The new normal (n) is defined as the input normal vector (n_i) minus 286 * the projection of itself (proj[n_i]_v) onto the bond vector (v): 287 288 * @verbatim 289 * v ^ 290 * | n = (n_i - proj[n_j]_v) 291 * proj[n_i]_v ^ |----x 292 * | | / 293 * | | / n_i 294 * | | / 295 * | |/ 296 * @endverbatim 297 298 * If n_i is parallel to v, a warning will be printed and no plane will be 299 * added. Obviously, n_i must not be parallel to v. 300 */ 301 static bool GetPlaneFromBond(const vtkBond& bond, const vtkVector3f& normal, vtkPlane* plane); 302 static bool GetPlaneFromBond( 303 const vtkAtom& atom1, const vtkAtom& atom2, const vtkVector3f& normal, vtkPlane* plane); 304 ///@} 305 306 /** 307 * Return true if a unit cell lattice is defined. 308 */ 309 bool HasLattice(); 310 311 /** 312 * Remove any unit cell lattice information from the molecule. 313 */ 314 void ClearLattice(); 315 316 ///@{ 317 /** 318 * The unit cell vectors. The matrix is stored using a row-major layout, with 319 * the vectors encoded as columns. 320 */ 321 void SetLattice(vtkMatrix3x3* matrix); 322 void SetLattice(const vtkVector3d& a, const vtkVector3d& b, const vtkVector3d& c); 323 ///@} 324 325 /** 326 * Get the unit cell lattice vectors. The matrix is stored using a row-major 327 * layout, with the vectors encoded as columns. Will return nullptr if no 328 * unit cell information is available. 329 * @sa GetLatticeOrigin 330 */ 331 vtkMatrix3x3* GetLattice(); 332 333 ///@{ 334 /** 335 * Get the unit cell lattice vectors, and optionally, the origin. 336 */ 337 void GetLattice(vtkVector3d& a, vtkVector3d& b, vtkVector3d& c); 338 void GetLattice(vtkVector3d& a, vtkVector3d& b, vtkVector3d& c, vtkVector3d& origin); 339 ///@} 340 341 ///@{ 342 /** 343 * Get the unit cell origin (for rendering purposes). 344 */ 345 vtkGetMacro(LatticeOrigin, vtkVector3d); 346 vtkSetMacro(LatticeOrigin, vtkVector3d); 347 ///@} 348 349 /** 350 * Get the array that defines the ghost type of each atom. 351 */ 352 vtkUnsignedCharArray* GetAtomGhostArray(); 353 354 /** 355 * Allocate ghost array for atoms. 356 */ 357 void AllocateAtomGhostArray(); 358 359 /** 360 * Get the array that defines the ghost type of each bond. 361 */ 362 vtkUnsignedCharArray* GetBondGhostArray(); 363 364 /** 365 * Allocate ghost array for bonds. 366 */ 367 void AllocateBondGhostArray(); 368 369 /** 370 * Initialize a molecule with an atom per input point. 371 * Parameters atomPositions and atomicNumberArray should have the same size. 372 */ 373 int Initialize( 374 vtkPoints* atomPositions, vtkDataArray* atomicNumberArray, vtkDataSetAttributes* atomData); 375 376 /** 377 * Overloads Initialize method. 378 */ Initialize(vtkPoints * atomPositions,vtkDataSetAttributes * atomData)379 int Initialize(vtkPoints* atomPositions, vtkDataSetAttributes* atomData) 380 { 381 return this->Initialize(atomPositions, nullptr, atomData); 382 } 383 384 /** 385 * Use input molecule points, atomic number and atomic data to initialize the new molecule. 386 */ 387 int Initialize(vtkMolecule* molecule); 388 389 ///@{ 390 /** 391 * Retrieve a molecule from an information vector. 392 */ 393 static vtkMolecule* GetData(vtkInformation* info); 394 static vtkMolecule* GetData(vtkInformationVector* v, int i = 0); 395 ///@} 396 397 /** 398 * Return the VertexData of the underlying graph 399 */ GetAtomData()400 vtkDataSetAttributes* GetAtomData() { return this->GetVertexData(); } 401 402 /** 403 * Return the EdgeData of the underlying graph 404 */ GetBondData()405 vtkDataSetAttributes* GetBondData() { return this->GetEdgeData(); } 406 407 /** 408 * Return the edge id from the underlying graph. 409 */ GetBondId(vtkIdType a,vtkIdType b)410 vtkIdType GetBondId(vtkIdType a, vtkIdType b) { return this->GetEdgeId(a, b); } 411 412 ///@{ 413 /** 414 * Get/Set the atomic number array name. 415 */ 416 vtkSetStringMacro(AtomicNumberArrayName); 417 vtkGetStringMacro(AtomicNumberArrayName); 418 ///@} 419 420 ///@{ 421 /** 422 * Get/Set the bond orders array name. 423 */ 424 vtkSetStringMacro(BondOrdersArrayName); 425 vtkGetStringMacro(BondOrdersArrayName); 426 ///@} 427 428 /** 429 * Return the actual size of the data in kibibytes (1024 bytes). This number 430 * is valid only after the pipeline has updated. The memory size 431 * returned is guaranteed to be greater than or equal to the 432 * memory required to represent the data (e.g., extra space in 433 * arrays, etc. are not included in the return value). 434 */ 435 unsigned long GetActualMemorySize() override; 436 437 protected: 438 vtkMolecule(); 439 ~vtkMolecule() override; 440 441 /** 442 * Copy bonds and atoms. 443 */ 444 virtual void CopyStructureInternal(vtkMolecule* m, bool deep); 445 446 /** 447 * Copy everything but bonds and atoms. 448 */ 449 virtual void CopyAttributesInternal(vtkMolecule* m, bool deep); 450 451 ///@{ 452 /** 453 * The graph superclass does not provide fast random access to the 454 * edge (bond) data. All random access is performed using a lookup 455 * table that must be rebuilt periodically. These allow for lazy 456 * building of the lookup table 457 */ 458 bool BondListIsDirty; SetBondListDirty()459 void SetBondListDirty() { this->BondListIsDirty = true; } 460 void UpdateBondList(); 461 vtkIdTypeArray* GetBondList(); 462 ///@} 463 464 friend class vtkAtom; 465 friend class vtkBond; 466 467 vtkAbstractElectronicData* ElectronicData; 468 vtkSmartPointer<vtkMatrix3x3> Lattice; 469 vtkVector3d LatticeOrigin; 470 471 vtkUnsignedCharArray* AtomGhostArray; 472 vtkUnsignedCharArray* BondGhostArray; 473 474 char* AtomicNumberArrayName; 475 char* BondOrdersArrayName; 476 477 private: 478 vtkMolecule(const vtkMolecule&) = delete; 479 void operator=(const vtkMolecule&) = delete; 480 }; 481 482 #endif 483