From 521898a2b5969bdb930ed8d4bc2fdc9631473383 Mon Sep 17 00:00:00 2001
From: Nicolas Vuaille <nicolas.vuaille@kitware.com>
Date: Tue, 3 Apr 2018 14:25:56 +0200
Subject: [PATCH] Molecule to polydata conversion

 * introduce vtkMoleculeToLinesFilter
 ** Create polydata with atom == point, bond == line cell. Copy data.

 * Fix AtomBall and BondStick conversion:
 ** set array name for bond orders and atomic numbers
 ** fix allocated size
---
 Domains/Chemistry/CMakeLists.txt              |  1 +
 Domains/Chemistry/Testing/Cxx/CMakeLists.txt  |  1 +
 .../Testing/Cxx/TestMoleculeToLines.cxx       | 62 +++++++++++++++++++
 .../Chemistry/vtkMoleculeToAtomBallFilter.cxx |  4 +-
 .../vtkMoleculeToBondStickFilter.cxx          |  4 +-
 .../Chemistry/vtkMoleculeToLinesFilter.cxx    | 50 +++++++++++++++
 Domains/Chemistry/vtkMoleculeToLinesFilter.h  | 51 +++++++++++++++
 7 files changed, 171 insertions(+), 2 deletions(-)
 create mode 100644 Domains/Chemistry/Testing/Cxx/TestMoleculeToLines.cxx
 create mode 100644 Domains/Chemistry/vtkMoleculeToLinesFilter.cxx
 create mode 100644 Domains/Chemistry/vtkMoleculeToLinesFilter.h

diff --git a/Domains/Chemistry/CMakeLists.txt b/Domains/Chemistry/CMakeLists.txt
index 5370210eea0..d9cdfc4aaa6 100644
--- a/Domains/Chemistry/CMakeLists.txt
+++ b/Domains/Chemistry/CMakeLists.txt
@@ -7,6 +7,7 @@ set(Module_SRCS
   vtkMoleculeMapper.cxx
   vtkMoleculeToAtomBallFilter.cxx
   vtkMoleculeToBondStickFilter.cxx
+  vtkMoleculeToLinesFilter.cxx
   vtkMoleculeToPolyDataFilter.cxx
   vtkPeriodicTable.cxx
   vtkPointSetToMoleculeFilter.cxx
diff --git a/Domains/Chemistry/Testing/Cxx/CMakeLists.txt b/Domains/Chemistry/Testing/Cxx/CMakeLists.txt
index c0235cc6722..b78e99f1fe5 100644
--- a/Domains/Chemistry/Testing/Cxx/CMakeLists.txt
+++ b/Domains/Chemistry/Testing/Cxx/CMakeLists.txt
@@ -28,6 +28,7 @@ vtk_add_test_cxx(vtkDomainsChemistryCxxTests tests
   TestMoleculeIOLegacy.cxx
   TestMoleculeSelection.cxx,NO_VALID
   TestMoleculeMapperPropertyUpdate.cxx
+  TestMoleculeToLines.cxx,NO_VALID
   TestMultiCylinderOn.cxx
   TestMultiCylinderOff.cxx
   TestPeriodicTable.cxx,NO_VALID
diff --git a/Domains/Chemistry/Testing/Cxx/TestMoleculeToLines.cxx b/Domains/Chemistry/Testing/Cxx/TestMoleculeToLines.cxx
new file mode 100644
index 00000000000..cd0a7c82511
--- /dev/null
+++ b/Domains/Chemistry/Testing/Cxx/TestMoleculeToLines.cxx
@@ -0,0 +1,62 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    TestMoleculeToLines.cxx
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#include "vtkTestUtilities.h"
+
+#include "vtkCMLMoleculeReader.h"
+#include "vtkCellData.h"
+#include "vtkDataSetAttributes.h"
+#include "vtkMolecule.h"
+#include "vtkMoleculeToLinesFilter.h"
+#include "vtkNew.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+
+#define CheckNumbers(name, first, second)                                                          \
+  if (first != second)                                                                             \
+  {                                                                                                \
+    cerr << "Error : wrong number of " << #name << ". Got " << first << " but expects " << second  \
+         << endl;                                                                                  \
+    return EXIT_FAILURE;                                                                           \
+  }
+
+int TestMoleculeToLines(int argc, char* argv[])
+{
+  char* fileName = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/porphyrin.cml");
+
+  // read molecule from cml file
+  vtkNew<vtkCMLMoleculeReader> reader;
+  reader->SetFileName(fileName);
+  reader->Update();
+  delete[] fileName;
+  vtkMolecule* molecule = reader->GetOutput();
+
+  // convert
+  vtkNew<vtkMoleculeToLinesFilter> converter;
+  converter->SetInputConnection(reader->GetOutputPort());
+  converter->Update();
+  vtkPolyData* poly = converter->GetOutput();
+
+  // check number of points, lines and associated data
+  CheckNumbers("points", poly->GetNumberOfPoints(), molecule->GetNumberOfAtoms());
+  CheckNumbers("lines", poly->GetNumberOfLines(), molecule->GetNumberOfBonds());
+  CheckNumbers("pointData",
+    poly->GetPointData()->GetNumberOfArrays(),
+    molecule->GetAtomData()->GetNumberOfArrays());
+  CheckNumbers("cellData",
+    poly->GetCellData()->GetNumberOfArrays(),
+    molecule->GetBondData()->GetNumberOfArrays());
+  return EXIT_SUCCESS;
+}
diff --git a/Domains/Chemistry/vtkMoleculeToAtomBallFilter.cxx b/Domains/Chemistry/vtkMoleculeToAtomBallFilter.cxx
index 70a32b21ae6..cb99c2543e9 100644
--- a/Domains/Chemistry/vtkMoleculeToAtomBallFilter.cxx
+++ b/Domains/Chemistry/vtkMoleculeToAtomBallFilter.cxx
@@ -59,6 +59,7 @@ int vtkMoleculeToAtomBallFilter::RequestData(
   vtkCellArray *polys = vtkCellArray::New();
   vtkPoints *points = vtkPoints::New();
   vtkUnsignedShortArray *atomicNums = vtkUnsignedShortArray::New();
+  atomicNums->SetName(input->GetAtomicNumberArrayName());
 
   // Initialize a SphereSource
   vtkSphereSource *sphereSource = vtkSphereSource::New();
@@ -71,7 +72,8 @@ int vtkMoleculeToAtomBallFilter::RequestData(
                    GetNumberOfPoints());
   polys->Allocate(numAtoms * sphereSource->GetOutput()->GetPolys()->
                   GetNumberOfCells());
-  atomicNums->Allocate(points->GetNumberOfPoints());
+  atomicNums->Allocate(numAtoms * sphereSource->GetOutput()->GetPoints()->
+                   GetNumberOfPoints());
 
   // Initialize some variables for later
   vtkIdType numCellPoints, *cellPoints;
diff --git a/Domains/Chemistry/vtkMoleculeToBondStickFilter.cxx b/Domains/Chemistry/vtkMoleculeToBondStickFilter.cxx
index e056c9b73cb..d510229de0a 100644
--- a/Domains/Chemistry/vtkMoleculeToBondStickFilter.cxx
+++ b/Domains/Chemistry/vtkMoleculeToBondStickFilter.cxx
@@ -52,6 +52,7 @@ int vtkMoleculeToBondStickFilter::RequestData(
   vtkCellArray *polys = vtkCellArray::New();
   vtkPoints *points = vtkPoints::New();
   vtkUnsignedShortArray *bondOrders = vtkUnsignedShortArray::New();
+  bondOrders->SetName(input->GetBondOrdersArrayName());
 
   // Initialize a CylinderSource
   vtkCylinderSource *cylSource = vtkCylinderSource::New();
@@ -64,7 +65,8 @@ int vtkMoleculeToBondStickFilter::RequestData(
                    GetNumberOfPoints());
   polys->Allocate(3 * numBonds * cylSource->GetOutput()->GetPolys()->
                   GetNumberOfCells());
-  bondOrders->Allocate(points->GetNumberOfPoints());
+  bondOrders->Allocate(3 * numBonds * cylSource->GetOutput()->GetPoints()->
+                   GetNumberOfPoints());
 
   // Create a transform object to map the cylinder source to the bond
   vtkTransform *xform = vtkTransform::New();
diff --git a/Domains/Chemistry/vtkMoleculeToLinesFilter.cxx b/Domains/Chemistry/vtkMoleculeToLinesFilter.cxx
new file mode 100644
index 00000000000..194f2fb4692
--- /dev/null
+++ b/Domains/Chemistry/vtkMoleculeToLinesFilter.cxx
@@ -0,0 +1,50 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkMoleculeToLinesFilter.cxx
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+#include "vtkMoleculeToLinesFilter.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkInformation.h"
+#include "vtkMolecule.h"
+#include "vtkPointData.h"
+
+vtkStandardNewMacro(vtkMoleculeToLinesFilter);
+
+//----------------------------------------------------------------------------
+int vtkMoleculeToLinesFilter::RequestData(vtkInformation*,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector)
+{
+  vtkMolecule* input = vtkMolecule::SafeDownCast(vtkDataObject::GetData(inputVector[0]));
+  vtkPolyData* output = vtkPolyData::SafeDownCast(vtkDataObject::GetData(outputVector));
+
+  vtkNew<vtkCellArray> bonds;
+  // 2 point ids + 1 VTKCellType = 3 values per bonds
+  bonds->Allocate(3 * input->GetNumberOfBonds());
+
+  for (vtkIdType bondInd = 0; bondInd < input->GetNumberOfBonds(); ++bondInd)
+  {
+    vtkBond bond = input->GetBond(bondInd);
+    vtkIdType ids[2] = { bond.GetBeginAtomId(), bond.GetEndAtomId() };
+    bonds->InsertNextCell(2, ids);
+  }
+
+  output->SetPoints(input->GetAtomicPositionArray());
+  output->SetLines(bonds);
+  output->GetPointData()->DeepCopy(input->GetAtomData());
+  output->GetCellData()->DeepCopy(input->GetBondData());
+
+  return 1;
+}
diff --git a/Domains/Chemistry/vtkMoleculeToLinesFilter.h b/Domains/Chemistry/vtkMoleculeToLinesFilter.h
new file mode 100644
index 00000000000..2f4a225966c
--- /dev/null
+++ b/Domains/Chemistry/vtkMoleculeToLinesFilter.h
@@ -0,0 +1,51 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkMoleculeToLinesFilter.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/**
+ * @class   vtkMoleculeToLinesFilter
+ * @brief Convert a molecule into a simple polydata with lines.
+ *
+ * vtkMoleculeToLinesFilter is a filter class that takes vtkMolecule as input and
+ * generates polydata on output.
+ * Conversion is done following this rules:
+ *  - 1 atom == 1 point
+ *  - 1 bond == 1 line (cell of type VTK_LINE)
+ *  - atom data is copied as point data
+ *  - bond data is copied as cell data
+ */
+
+#ifndef vtkMoleculeToLinesFilter_h
+#define vtkMoleculeToLinesFilter_h
+
+#include "vtkDomainsChemistryModule.h" // For export macro
+#include "vtkMoleculeToPolyDataFilter.h"
+
+class VTKDOMAINSCHEMISTRY_EXPORT vtkMoleculeToLinesFilter : public vtkMoleculeToPolyDataFilter
+{
+public:
+  static vtkMoleculeToLinesFilter* New();
+  vtkTypeMacro(vtkMoleculeToLinesFilter, vtkMoleculeToPolyDataFilter);
+
+protected:
+  vtkMoleculeToLinesFilter() = default;
+  ~vtkMoleculeToLinesFilter() = default;
+
+  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
+
+private:
+  vtkMoleculeToLinesFilter(const vtkMoleculeToLinesFilter&) = delete;
+  void operator=(const vtkMoleculeToLinesFilter&) = delete;
+};
+
+#endif
-- 
GitLab