From 90ff44ccb32c60555dd5c59ae78f48f3bca891c8 Mon Sep 17 00:00:00 2001
From: Vickie Lynch <lynchve@ornl.gov>
Date: Fri, 3 Feb 2012 14:14:07 -0500
Subject: [PATCH] Refs #4677 Sort by point groups(same as last 3 commits to
 iteration33)

---
 .../Crystal/inc/MantidCrystal/SortHKL.h       |   3 +
 Code/Mantid/Framework/Crystal/src/SortHKL.cpp |  71 +++++--
 Code/Mantid/Framework/Geometry/CMakeLists.txt |   2 +
 .../inc/MantidGeometry/Crystal/PointGroup.h   | 197 ++++++++++++++++++
 .../Geometry/src/Crystal/PointGroup.cpp       |  34 +++
 5 files changed, 292 insertions(+), 15 deletions(-)
 create mode 100644 Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroup.h
 create mode 100644 Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp

diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SortHKL.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SortHKL.h
index b0860650b2c..ec0be7d901f 100644
--- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SortHKL.h
+++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/SortHKL.h
@@ -3,6 +3,7 @@
     
 #include "MantidKernel/System.h"
 #include "MantidAPI/Algorithm.h" 
+#include "MantidGeometry/Crystal/PointGroup.h"
 
 namespace Mantid
 {
@@ -29,6 +30,8 @@ namespace Crystal
     virtual const std::string category() const { return "Crystal;DataHandling\\Text";}
     
   private:
+    /// Point Groups possible
+    std::vector<Mantid::Geometry::PointGroup_sptr> m_pointGroups;
     /// Sets documentation strings for this algorithm
     virtual void initDocs();
     /// Initialise the properties
diff --git a/Code/Mantid/Framework/Crystal/src/SortHKL.cpp b/Code/Mantid/Framework/Crystal/src/SortHKL.cpp
index 7362d0e5bd7..9afe0cb421c 100644
--- a/Code/Mantid/Framework/Crystal/src/SortHKL.cpp
+++ b/Code/Mantid/Framework/Crystal/src/SortHKL.cpp
@@ -8,6 +8,7 @@
 #include "MantidDataObjects/Peak.h"
 #include "MantidDataObjects/PeaksWorkspace.h"
 #include "MantidGeometry/Instrument/RectangularDetector.h"
+#include "MantidGeometry/Crystal/PointGroup.h"
 #include "MantidKernel/Strings.h"
 #include "MantidKernel/System.h"
 #include "MantidKernel/Utils.h"
@@ -37,6 +38,7 @@ namespace Crystal
    */
   SortHKL::SortHKL()
   {
+    m_pointGroups = getAllPointGroups();
   }
     
   //----------------------------------------------------------------------------------------------
@@ -62,6 +64,12 @@ namespace Crystal
   {
     declareProperty(new WorkspaceProperty<PeaksWorkspace>("InputWorkspace","",Direction::InOut),
         "An input PeaksWorkspace with an instrument.");
+    std::vector<std::string> propOptions;
+    for (size_t i=0; i<m_pointGroups.size(); ++i)
+      propOptions.push_back( m_pointGroups[i]->getName() );
+    declareProperty("PointGroup", propOptions[0],new ListValidator(propOptions),
+      "Which point group applies to this crystal?");
+
     declareProperty(new WorkspaceProperty<API::ITableWorkspace>("DuplicatesStatisticsTable","Statistics",Direction::Output));
 
   }
@@ -72,7 +80,19 @@ namespace Crystal
   void SortHKL::exec()
   {
 
-    PeaksWorkspace_sptr peaksW = getProperty("InputWorkspace");
+    PeaksWorkspace_sptr InPeaksW = getProperty("InputWorkspace");
+    // HKL will be overwritten by equivalent HKL but never seen by user
+    PeaksWorkspace_sptr peaksW = InPeaksW->clone();
+    peaksW->setName("PeaksByEquivalentHKL");
+    
+    //Use the primitive by default
+    PointGroup_sptr pointGroup(new PointGroupLaue1());
+    //Get it from the property
+    std::string pointGroupName = getPropertyValue("PointGroup");
+    for (size_t i=0; i<m_pointGroups.size(); ++i)
+      if (m_pointGroups[i]->getName() == pointGroupName)
+        pointGroup = m_pointGroups[i];
+
     API::ITableWorkspace_sptr t = WorkspaceFactory::Instance().createTable("TableWorkspace");
     t->addColumn("double","h");
     t->addColumn("double","k");
@@ -89,16 +109,31 @@ namespace Crystal
     t->addColumn("double","Sigma.min");
     t->addColumn("double","Sigma.max");
     t->addColumn("double","Sigma.median");
+    int NumberPeaks = peaksW->getNumberPeaks();
+    for (int i = 0; i < NumberPeaks; i++)
+    {
+      Peak & peak1 = peaksW->getPeaks()[i];
+      V3D hkl1 = peak1.getHKL();
+      std::string bank1 = peak1.getBankName();
+      for (int j = i+1; j < NumberPeaks; j++)
+      {
+        Peak & peak2 = peaksW->getPeaks()[j];
+        V3D hkl2 = peak2.getHKL();
+        std::string bank2 = peak2.getBankName();
+        if (pointGroup->isEquivalent(hkl1,hkl2) && bank1.compare(bank2) == 0)
+          peaksW->getPeaks()[j].setHKL(hkl1);
+      }
+    }
 
     std::vector< std::pair<std::string, bool> > criteria;
     // Sort by detector ID then descending wavelength
+    criteria.push_back( std::pair<std::string, bool>("BankName", true) );
     criteria.push_back( std::pair<std::string, bool>("H", true) );
     criteria.push_back( std::pair<std::string, bool>("K", true) );
     criteria.push_back( std::pair<std::string, bool>("L", true) );
-    criteria.push_back( std::pair<std::string, bool>("BankName", true) );
+    InPeaksW->sort(criteria);
     peaksW->sort(criteria);
 
-    int NumberPeaks = peaksW->getNumberPeaks();
     std::vector<double> data, err;
     V3D hkl1;
     std::string bank1;
@@ -121,24 +156,31 @@ namespace Crystal
         err.push_back(peak2.getSigmaIntensity());
         if(i == NumberPeaks-1)
         {
+          if(static_cast<int>(data.size()) > 1)
+          {
+            Outliers(data,err);
+            Statistics stats = getStatistics(data);
+            TableRow r = t->appendRow();
+            r <<peak1.getH()<<peak1.getK()<<peak1.getL()<<bank1<<static_cast<int>(data.size())<<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
+            stats = getStatistics(err);
+            r <<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
+          }
           Outliers(data,err);
-          Statistics stats = getStatistics(data);
-          TableRow r = t->appendRow();
-          r <<peak1.getH()<<peak1.getK()<<peak1.getL()<<bank1<<static_cast<int>(data.size())<<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
-          stats = getStatistics(err);
-          r <<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
           data.clear();
           err.clear();
         }
       }
       else
       {
-        Outliers(data,err);
-        Statistics stats = getStatistics(data);
-        TableRow r = t->appendRow();
-        r <<peak1.getH()<<peak1.getK()<<peak1.getL()<<bank1<<static_cast<int>(data.size())<<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
-        stats = getStatistics(err);
-        r <<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
+        if(static_cast<int>(data.size()) > 1)
+        {
+          Outliers(data,err);
+          Statistics stats = getStatistics(data);
+          TableRow r = t->appendRow();
+          r <<peak1.getH()<<peak1.getK()<<peak1.getL()<<bank1<<static_cast<int>(data.size())<<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
+          stats = getStatistics(err);
+          r <<stats.mean<< stats.standard_deviation<< stats.minimum<< stats.maximum<< stats.median;
+        }
         data.clear();
         err.clear();
         hkl1 = hkl2;
@@ -154,7 +196,6 @@ namespace Crystal
   }
   void SortHKL::Outliers(std::vector<double>& data, std::vector<double>& err)
   {
-      if(static_cast<int>(data.size()) < 2) return;
       Statistics stats = getStatistics(data);
       if(stats.standard_deviation == 0.)return;
       for (int i = static_cast<int>(data.size())-1; i>=0; i--)
diff --git a/Code/Mantid/Framework/Geometry/CMakeLists.txt b/Code/Mantid/Framework/Geometry/CMakeLists.txt
index 761efc023cd..bdcf29dff52 100644
--- a/Code/Mantid/Framework/Geometry/CMakeLists.txt
+++ b/Code/Mantid/Framework/Geometry/CMakeLists.txt
@@ -3,6 +3,7 @@ set ( SRC_FILES
 	src/Crystal/IndexingUtils.cpp
 	src/Crystal/ReducedCell.cpp
 	src/Crystal/OrientedLattice.cpp
+	src/Crystal/PointGroup.cpp
 	src/Crystal/ReflectionCondition.cpp
 	src/Crystal/UnitCell.cpp
 	src/IObjComponent.cpp
@@ -96,6 +97,7 @@ set ( INC_FILES
 	inc/MantidGeometry/Crystal/IndexingUtils.h
 	inc/MantidGeometry/Crystal/ReducedCell.h
 	inc/MantidGeometry/Crystal/OrientedLattice.h
+	inc/MantidGeometry/Crystal/PointGroup.h
 	inc/MantidGeometry/Crystal/ReflectionCondition.h
 	inc/MantidGeometry/Crystal/UnitCell.h
 	inc/MantidGeometry/DllConfig.h
diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroup.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroup.h
new file mode 100644
index 00000000000..d523bde9a65
--- /dev/null
+++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/PointGroup.h
@@ -0,0 +1,197 @@
+#ifndef MANTID_GEOMETRY_POINTGROUP_H_
+#define MANTID_GEOMETRY_POINTGROUP_H_
+    
+#include "MantidGeometry/DllConfig.h"
+#include "MantidKernel/V3D.h"
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <string>
+
+namespace Mantid
+{
+namespace Geometry
+{
+
+  using Kernel::V3D;
+  /** A class containing the Point Groups for a crystal.
+   * 
+   * @author Vickie Lynch
+   * @date 2012-02-02
+   */
+  class MANTID_GEOMETRY_DLL PointGroup 
+  {
+  public:
+    PointGroup() {}
+    virtual ~PointGroup() {}
+    /// Name of the point group
+    virtual std::string getName() = 0;
+    /// Return true if the hkls are in same group
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) = 0;
+  };
+
+  //------------------------------------------------------------------------
+  /** -1 (Triclinic) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue1 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "-1 (Triclinic)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,-l)); }  
+  };
+
+  //------------------------------------------------------------------------
+  /** 1 2/m 1 (Monoclinic, unique axis b) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue2 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "1 2/m 1 (Monoclinic, unique axis b)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(-h,k,-l)) || (hkl2 == V3D(h,-k,l)); }  
+  };
+
+  //------------------------------------------------------------------------
+  /** 1 1 2/m (Monoclinic, unique axis c) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue3 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "1 1 2/m (Monoclinic, unique axis c)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)); }  
+  };
+
+  //------------------------------------------------------------------------
+  /** mmm (Orthorombic) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue4 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "mmm (Orthorombic)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-h,k,-l)) || (hkl2 == V3D(h,-k,-l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(h,-k,l)) || (hkl2 == V3D(-h,k,l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** 4/m (Tetragonal) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue5 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "4/m (Tetragonal)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-k,h,l)) || (hkl2 == V3D(k,-h,l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(k,-h,-l)) || (hkl2 == V3D(-k,h,-l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** 4/mmm (Tetragonal) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue6 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "4/mmm (Tetragonal)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-k,h,l)) || (hkl2 == V3D(k,-h,l)) || (hkl2 == V3D(-h,k,-l)) || (hkl2 == V3D(h,-k,-l)) || (hkl2 == V3D(k,h,-l)) || (hkl2 == V3D(-k,-h,-l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(k,-h,-l)) || (hkl2 == V3D(-k,h,-l)) || (hkl2 == V3D(h,-k,l)) || (hkl2 == V3D(-h,k,l)) || (hkl2 == V3D(-k,-h,l)) || (hkl2 == V3D(k,h,l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** -3 (Trigonal - Hexagonal) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue7 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "-3 (Trigonal - Hexagonal)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-k,h-k,l)) || (hkl2 == V3D(-h+k,-h,l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(k,-h+k,-l)) || (hkl2 == V3D(h-k,h,-l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** -3m1 (Trigonal - Rhombohedral) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue8 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "-3m1 (Trigonal - Rhombohedral)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+      { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-k,h-k,l)) || (hkl2 == V3D(-h+k,-h,l)) || (hkl2 == V3D(-k,-h,-l)) || (hkl2 == V3D(-h+k,k,-l)) || (hkl2 == V3D(h,h-k,-l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(k,-h+k,-l)) || (hkl2 == V3D(h-k,h,-l)) || (hkl2 == V3D(k,h,l)) || (hkl2 == V3D(h-k,-k,l)) || (hkl2 == V3D(-h,-h+k,l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** -31m (Trigonal - Rhombohedral) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue9 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "-31m (Trigonal - Rhombohedral)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-k,h-k,l)) || (hkl2 == V3D(-h+k,-h,l)) || (hkl2 == V3D(k,h,-l)) || (hkl2 == V3D(h-k,-k,-l)) || (hkl2 == V3D(-h,-h+k,-l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(k,-h+k,-l)) || (hkl2 == V3D(h-k,h,-l)) || (hkl2 == V3D(-k,-h,l)) || (hkl2 == V3D(-h+k,k,l)) || (hkl2 == V3D(h,h-k,l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /**  6/m (Hexagonal) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue10 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "6/m (Hexagonal)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-k,h-k,l)) || (hkl2 == V3D(-h+k,-h,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(k,-h+k,l)) || (hkl2 == V3D(h-k,h,l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(k,-h+k,-l)) || (hkl2 == V3D(h-k,h,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(-k,h-k,-l)) || (hkl2 == V3D(-h+k,-h,-l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** 6/mmm (Hexagonal) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue11 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "6/mmm (Hexagonal)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-k,h-k,l)) || (hkl2 == V3D(-h+k,-h,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(k,-h+k,l)) || (hkl2 == V3D(h-k,h,l)) || (hkl2 == V3D(k,h,-l)) || (hkl2 == V3D(h-k,-k,-l)) || (hkl2 == V3D(-h,-h+k,-l)) || (hkl2 == V3D(-k,-h,-l)) || (hkl2 == V3D(-h+k,k,-l)) || (hkl2 == V3D(h,h-k,-l)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(k,-h+k,-l)) || (hkl2 == V3D(h-k,h,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(-k,h-k,-l)) || (hkl2 == V3D(-h+k,-h,-l)) || (hkl2 == V3D(-k,-h,l)) || (hkl2 == V3D(-h+k,k,l)) || (hkl2 == V3D(h,h-k,l)) || (hkl2 == V3D(k,h,l)) || (hkl2 == V3D(h-k,-k,l)) || (hkl2 == V3D(-h,-h+k,l)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** m-3 (Cubic) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue12 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "m-3 (Cubic)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-h,k,-l)) || (hkl2 == V3D(h,-k,-l)) || (hkl2 == V3D(l,h,k)) || (hkl2 == V3D(l,-h,-k)) || (hkl2 == V3D(-l,-h,k)) || (hkl2 == V3D(-l,h,-k)) || (hkl2 == V3D(k,l,h)) || (hkl2 == V3D(-k,l,-h)) || (hkl2 == V3D(k,-l,-h)) || (hkl2 == V3D(-k,-l,h)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(h,-k,l)) || (hkl2 == V3D(-h,k,l)) || (hkl2 == V3D(-l,-h,-k)) || (hkl2 == V3D(-l,h,k)) || (hkl2 == V3D(l,h,-k)) || (hkl2 == V3D(l,-h,k)) || (hkl2 == V3D(-k,-l,-h)) || (hkl2 == V3D(k,-l,h)) || (hkl2 == V3D(-k,l,h)) || (hkl2 == V3D(k,l,-h)); }
+  };
+
+  //------------------------------------------------------------------------
+  /** m-3m (Cubic) PointGroup */
+  class MANTID_GEOMETRY_DLL PointGroupLaue13 : public PointGroup
+  {
+  public:
+    /// Name of the point group
+    virtual std::string getName() { return "m-3m (Cubic)"; }
+    /// Return true if the hkls are equivalent.
+    virtual bool isEquivalent(V3D hkl, V3D hkl2) 
+     { double h=hkl[0];double k=hkl[1];double l=hkl[2]; return (hkl2 == V3D(h,k,l)) || (hkl2 == V3D(-h,-k,l)) || (hkl2 == V3D(-h,k,-l)) || (hkl2 == V3D(h,-k,-l)) || (hkl2 == V3D(l,h,k)) || (hkl2 == V3D(l,-h,-k)) || (hkl2 == V3D(-l,-h,k)) || (hkl2 == V3D(-l,h,-k)) || (hkl2 == V3D(k,l,h)) || (hkl2 == V3D(-k,l,-h)) || (hkl2 == V3D(k,-l,-h)) || (hkl2 == V3D(-k,-l,h)) || (hkl2 == V3D(k,h,-l)) || (hkl2 == V3D(-k,-h,-l)) || (hkl2 == V3D(k,-h,l)) || (hkl2 == V3D(-k,h,l)) || (hkl2 == V3D(h,l,-k)) || (hkl2 == V3D(-h,l,k)) || (hkl2 == V3D(-h,-l,-k)) || (hkl2 == V3D(h,-l,k)) || (hkl2 == V3D(l,k,-h)) || (hkl2 == V3D(l,-k,h)) || (hkl2 == V3D(-l,k,h)) || (hkl2 == V3D(-l,-k,-h)) || (hkl2 == V3D(-h,-k,-l)) || (hkl2 == V3D(h,k,-l)) || (hkl2 == V3D(h,-k,l)) || (hkl2 == V3D(-h,k,l)) || (hkl2 == V3D(-l,-h,-k)) || (hkl2 == V3D(-l,h,k)) || (hkl2 == V3D(l,h,-k)) || (hkl2 == V3D(l,-h,k)) || (hkl2 == V3D(-k,-l,-h)) || (hkl2 == V3D(k,-l,h)) || (hkl2 == V3D(-k,l,h)) || (hkl2 == V3D(k,l,-h)) || (hkl2 == V3D(-k,-h,l)) || (hkl2 == V3D(k,h,l)) || (hkl2 == V3D(-k,h,-l)) || (hkl2 == V3D(k,-h,-l)) || (hkl2 == V3D(-h,-l,k)) || (hkl2 == V3D(h,-l,-k)) || (hkl2 == V3D(h,l,k)) || (hkl2 == V3D(-h,l,-k)) || (hkl2 == V3D(-l,-k,h)) || (hkl2 == V3D(-l,k,-h)) || (hkl2 == V3D(l,-k,-h)) || (hkl2 == V3D(l,k,h)); }
+  };
+
+
+  /// Shared pointer to a PointGroup
+  typedef boost::shared_ptr<PointGroup> PointGroup_sptr;
+
+  MANTID_GEOMETRY_DLL std::vector<PointGroup_sptr> getAllPointGroups();
+
+} // namespace Mantid
+} // namespace Geometry
+
+#endif  /* MANTID_GEOMETRY_POINTGROUP_H_ */
diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp
new file mode 100644
index 00000000000..bb65c429c7a
--- /dev/null
+++ b/Code/Mantid/Framework/Geometry/src/Crystal/PointGroup.cpp
@@ -0,0 +1,34 @@
+#include "MantidGeometry/Crystal/PointGroup.h"
+#include "MantidKernel/System.h"
+
+namespace Mantid
+{
+namespace Geometry
+{
+
+  /** @return a vector with all possible PointGroup objects */
+  std::vector<PointGroup_sptr> getAllPointGroups()
+  {
+    std::vector<PointGroup_sptr> out;
+    out.push_back(PointGroup_sptr(new PointGroupLaue1() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue2() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue3() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue4() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue5() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue6() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue7() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue8() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue9() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue10() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue11() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue12() ));
+    out.push_back(PointGroup_sptr(new PointGroupLaue13() ));
+    return out;
+  }
+
+
+
+
+} // namespace Mantid
+} // namespace Geometry
+
-- 
GitLab