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 "vtkUndirectedGraph.h" 74 #include "vtkSmartPointer.h" // For vtkSmartPointer 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() 109 { 110 return this->AppendAtom(0, vtkVector3f(0, 0, 0)); 111 } 112 113 /** 114 * Add new atom with the specified atomic number and position. Return a 115 * vtkAtom that refers to the new atom. 116 */ 117 vtkAtom AppendAtom(unsigned short atomicNumber, const vtkVector3f &pos); 118 119 /** 120 * Convenience methods to append a new atom with the specified atomic number 121 * and position. 122 */ AppendAtom(unsigned short atomicNumber,double x,double y,double z)123 vtkAtom AppendAtom(unsigned short atomicNumber, double x, double y, double z) 124 { 125 return this->AppendAtom(atomicNumber, vtkVector3f(x, y, z)); 126 } 127 128 /** 129 * Return a vtkAtom that refers to the atom with the specified id. 130 */ 131 vtkAtom GetAtom(vtkIdType atomId); 132 133 /** 134 * Return the number of atoms in the molecule. 135 */ 136 vtkIdType GetNumberOfAtoms(); 137 138 //@{ 139 /** 140 * Add a bond between the specified atoms, optionally setting the 141 * bond order (default: 1). Return a vtkBond object referring to the 142 * new bond. 143 */ 144 vtkBond AppendBond(vtkIdType atom1, vtkIdType atom2, 145 unsigned short order = 1); 146 vtkBond AppendBond(const vtkAtom &atom1, const vtkAtom &atom2, 147 unsigned short order = 1) 148 { 149 return this->AppendBond(atom1.Id, atom2.Id, order); 150 } 151 //@} 152 153 /** 154 * Return a vtkAtom that refers to the bond with the specified id. 155 */ 156 vtkBond GetBond(vtkIdType bondId); 157 158 /** 159 * Return the number of bonds in the molecule. 160 */ 161 vtkIdType GetNumberOfBonds(); 162 163 /** 164 * Return the atomic number of the atom with the specified id. 165 */ 166 unsigned short GetAtomAtomicNumber(vtkIdType atomId); 167 168 /** 169 * Set the atomic number of the atom with the specified id. 170 */ 171 void SetAtomAtomicNumber(vtkIdType atomId, 172 unsigned short atomicNum); 173 174 //@{ 175 /** 176 * Set the position of the atom with the specified id. 177 */ 178 void SetAtomPosition(vtkIdType atomId, const vtkVector3f &pos); 179 void SetAtomPosition(vtkIdType atomId, double x, double y, double z); 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 //@} 189 190 //@{ 191 /** 192 * Get/Set the bond order of the bond with the specified id 193 */ 194 void SetBondOrder(vtkIdType bondId, unsigned short order); 195 unsigned short GetBondOrder(vtkIdType bondId); 196 //@} 197 198 /** 199 * Get the bond length of the bond with the specified id 200 201 * \note If the associated vtkBond object is already available, 202 * vtkBond::GetBondLength is potentially much faster than this 203 * function, as a list of all bonds may need to be constructed to 204 * locate the appropriate bond. 205 * \sa UpdateBondList() 206 */ 207 double GetBondLength(vtkIdType bondId); 208 209 //@{ 210 /** 211 * Access the raw arrays used in this vtkMolecule instance 212 */ 213 vtkPoints * GetAtomicPositionArray(); 214 vtkUnsignedShortArray * GetAtomicNumberArray(); 215 vtkUnsignedShortArray * GetBondOrdersArray(); 216 //@} 217 218 //@{ 219 /** 220 * Set/Get the AbstractElectronicData-subclassed object for this molecule. 221 */ 222 vtkGetObjectMacro(ElectronicData, vtkAbstractElectronicData); 223 virtual void SetElectronicData(vtkAbstractElectronicData*); 224 //@} 225 226 /** 227 * Performs the same operation as ShallowCopy(), 228 * but instead of reporting an error for an incompatible graph, 229 * returns false. 230 */ 231 bool CheckedShallowCopy(vtkGraph *g) override; 232 233 /** 234 * Performs the same operation as DeepCopy(), 235 * but instead of reporting an error for an incompatible graph, 236 * returns false. 237 */ 238 bool CheckedDeepCopy(vtkGraph *g) override; 239 240 /** 241 * Shallow copies the data object into this molecule. 242 */ 243 void ShallowCopy(vtkDataObject *obj) override; 244 245 /** 246 * Deep copies the data object into this molecule. 247 */ 248 void DeepCopy(vtkDataObject *obj) override; 249 250 /** 251 * Shallow copies the atoms and bonds from @a m into @a this. 252 */ 253 virtual void ShallowCopyStructure(vtkMolecule *m); 254 255 /** 256 * Deep copies the atoms and bonds from @a m into @a this. 257 */ 258 virtual void DeepCopyStructure(vtkMolecule *m); 259 260 /** 261 * Shallow copies attributes (i.e. everything besides atoms and bonds) from 262 * @a m into @a this. 263 */ 264 virtual void ShallowCopyAttributes(vtkMolecule *m); 265 266 /** 267 * Deep copies attributes (i.e. everything besides atoms and bonds) from 268 * @a m into @a this. 269 */ 270 virtual void DeepCopyAttributes(vtkMolecule *m); 271 272 //@{ 273 /** 274 * Obtain the plane that passes through the indicated bond with the given 275 * normal. If the plane is set successfully, the function returns true. 276 277 * If the normal is not orthogonal to the bond, a new normal will be 278 * constructed in such a way that the plane will be orthogonal to 279 * the plane spanned by the bond vector and the input normal vector. 280 281 * This ensures that the plane passes through the bond, and the 282 * normal is more of a "hint" indicating the orientation of the plane. 283 284 * The new normal (n) is defined as the input normal vector (n_i) minus 285 * the projection of itself (proj[n_i]_v) onto the bond vector (v): 286 287 * @verbatim 288 * v ^ 289 * | n = (n_i - proj[n_j]_v) 290 * proj[n_i]_v ^ |----x 291 * | | / 292 * | | / n_i 293 * | | / 294 * | |/ 295 * @endverbatim 296 297 * If n_i is parallel to v, a warning will be printed and no plane will be 298 * added. Obviously, n_i must not be parallel to v. 299 */ 300 static bool GetPlaneFromBond(const vtkBond &bond, const vtkVector3f &normal, 301 vtkPlane *plane); 302 static bool GetPlaneFromBond(const vtkAtom &atom1, const vtkAtom &atom2, 303 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, 323 const vtkVector3d &b, 324 const vtkVector3d &c); 325 //@} 326 327 /** 328 * Get the unit cell lattice vectors. The matrix is stored using a row-major 329 * layout, with the vectors encoded as columns. Will return nullptr if no 330 * unit cell information is available. 331 * @sa GetLatticeOrigin 332 */ 333 vtkMatrix3x3* GetLattice(); 334 335 //@{ 336 /** 337 * Get the unit cell lattice vectors, and optionally, the origin. 338 */ 339 void GetLattice(vtkVector3d &a, vtkVector3d &b, vtkVector3d &c); 340 void GetLattice(vtkVector3d &a, vtkVector3d &b, vtkVector3d &c, 341 vtkVector3d &origin); 342 //@} 343 344 //@{ 345 /** 346 * Get the unit cell origin (for rendering purposes). 347 */ 348 vtkGetMacro(LatticeOrigin, vtkVector3d) 349 vtkSetMacro(LatticeOrigin, vtkVector3d) 350 //@} 351 352 /** 353 * Get the array that defines the ghost type of each atom. 354 */ 355 vtkUnsignedCharArray* GetAtomGhostArray(); 356 357 /** 358 * Allocate ghost array for atoms. 359 */ 360 void AllocateAtomGhostArray(); 361 362 /** 363 * Get the array that defines the ghost type of each bond. 364 */ 365 vtkUnsignedCharArray* GetBondGhostArray(); 366 367 /** 368 * Allocate ghost array for bonds. 369 */ 370 void AllocateBondGhostArray(); 371 372 /** 373 * Initialize a molecule with an atom per input point. 374 * Parameters atomPositions and atomicNumberArray should have the same size. 375 */ 376 int Initialize(vtkPoints* atomPositions, 377 vtkDataArray* atomicNumberArray, 378 vtkDataSetAttributes* atomData); 379 380 /** 381 * Overloads Initialize method. 382 */ Initialize(vtkPoints * atomPositions,vtkDataSetAttributes * atomData)383 int Initialize(vtkPoints* atomPositions, 384 vtkDataSetAttributes* atomData) 385 { 386 return this->Initialize(atomPositions, nullptr, atomData); 387 } 388 389 /** 390 * Use input molecule points, atomic number and atomic data to initialize the new molecule. 391 */ 392 int Initialize(vtkMolecule* molecule); 393 394 //@{ 395 /** 396 * Retrieve a molecule from an information vector. 397 */ 398 static vtkMolecule* GetData(vtkInformation *info); 399 static vtkMolecule* GetData(vtkInformationVector *v, int i=0); 400 //@} 401 402 /** 403 * Return the VertexData of the underlying graph 404 */ GetAtomData()405 vtkDataSetAttributes* GetAtomData() 406 { 407 return this->GetVertexData(); 408 } 409 410 /** 411 * Return the EdgeData of the underlying graph 412 */ GetBondData()413 vtkDataSetAttributes* GetBondData() 414 { 415 return this->GetEdgeData(); 416 } 417 418 /** 419 * Return the edge id from the underlying graph. 420 */ GetBondId(vtkIdType a,vtkIdType b)421 vtkIdType GetBondId(vtkIdType a, vtkIdType b) 422 { 423 return this->GetEdgeId(a, b); 424 } 425 426 //@{ 427 /** 428 * Get/Set the atomic number array name. 429 */ 430 vtkSetStringMacro(AtomicNumberArrayName); 431 vtkGetStringMacro(AtomicNumberArrayName); 432 //@} 433 434 //@{ 435 /** 436 * Get/Set the bond orders array name. 437 */ 438 vtkSetStringMacro(BondOrdersArrayName); 439 vtkGetStringMacro(BondOrdersArrayName); 440 //@} 441 442 protected: 443 vtkMolecule(); 444 ~vtkMolecule() override; 445 446 /** 447 * Copy bonds and atoms. 448 */ 449 virtual void CopyStructureInternal(vtkMolecule *m, bool deep); 450 451 /** 452 * Copy everything but bonds and atoms. 453 */ 454 virtual void CopyAttributesInternal(vtkMolecule *m, bool deep); 455 456 //@{ 457 /** 458 * The graph superclass does not provide fast random access to the 459 * edge (bond) data. All random access is performed using a lookup 460 * table that must be rebuilt periodically. These allow for lazy 461 * building of the lookup table 462 */ 463 bool BondListIsDirty; SetBondListDirty()464 void SetBondListDirty() {this->BondListIsDirty = true;} 465 void UpdateBondList(); 466 vtkIdTypeArray* GetBondList(); 467 //@} 468 469 friend class vtkAtom; 470 friend class vtkBond; 471 472 vtkAbstractElectronicData *ElectronicData; 473 vtkSmartPointer<vtkMatrix3x3> Lattice; 474 vtkVector3d LatticeOrigin; 475 476 vtkUnsignedCharArray* AtomGhostArray; 477 vtkUnsignedCharArray* BondGhostArray; 478 479 char* AtomicNumberArrayName; 480 char* BondOrdersArrayName; 481 482 private: 483 vtkMolecule(const vtkMolecule&) = delete; 484 void operator=(const vtkMolecule&) = delete; 485 }; 486 487 #endif 488