Skip to content

Libs/Optimize/ParticleSystem.h

Namespaces

Name
shapeworks
User usage reporting (telemetry)

Classes

Name
class shapeworks::ParticleSystem
A facade class managing interactions with a particle system.

Source code

#pragma once

#include <map>
#include <random>
#include <vector>

#include "Libs/Optimize/Container/GenericContainer.h"
#include "Libs/Optimize/Domain/ParticleDomain.h"
#include "Libs/Optimize/Neighborhood/ParticleNeighborhood.h"
#include "Observer.h"
#include "ParticleEvents.h"
#include "itkCommand.h"
#include "itkDataObject.h"
#include "itkEventObject.h"
#include "itkObjectFactory.h"
#include "itkPoint.h"
#include "itkWeakPointer.h"
#include "vnl/vnl_inverse.h"
#include "vnl/vnl_matrix_fixed.h"
#include "vnl/vnl_vector_fixed.h"

namespace shapeworks {
class ParticleSystem : public itk::DataObject {
 public:
  static constexpr int VDimension = 3;

  typedef ParticleSystem Self;
  typedef DataObject Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;
  typedef itk::WeakPointer<const Self> ConstWeakPointer;

  itkNewMacro(Self);

  itkTypeMacro(ParticleSystem, itk::DataObject);

  itkStaticConstMacro(Dimension, unsigned int, VDimension);

  using DomainType = shapeworks::ParticleDomain;

  typedef itk::Point<double, VDimension> PointType;

  typedef ParticleNeighborhood NeighborhoodType;

  typedef GenericContainer<PointType> PointContainerType;

  typedef NeighborhoodType::PointVectorType PointVectorType;

  //  typedef Transform<double, VDimension, VDimension> TransformType;
  typedef vnl_matrix_fixed<double, VDimension + 1, VDimension + 1> TransformType;
  typedef vnl_vector_fixed<double, VDimension> VectorType;
  typedef vnl_matrix<double> VnlMatrixType;

  void RegisterObserver(Observer *attr);

  void SynchronizePositions() {
    for (unsigned int d = 0; d < this->GetNumberOfDomains(); d++) {
      for (unsigned int p = 0; p < this->GetNumberOfParticles(d); p++) {
        this->SetPosition(this->GetPosition(p, d), p, d);
      }
    }
  }

  unsigned long int GetNumberOfParticles(unsigned int d = 0) const { return m_Positions[d]->GetSize(); }

  const PointType &AddPosition(const PointType &, unsigned int d = 0);
  const PointType &SetPosition(const PointType &, unsigned long int k, unsigned int d = 0);

  void RemovePosition(unsigned long int k, unsigned int d = 0);

  PointType &GetPosition(unsigned long int k, unsigned int d = 0) { return m_Positions[d]->operator[](k); }
  const PointType &GetPosition(unsigned long int k, unsigned int d = 0) const { return m_Positions[d]->operator[](k); }
  PointType GetTransformedPosition(unsigned long int k, unsigned int d = 0) const {
    return this->TransformPoint(m_Positions[d]->operator[](k), m_Transforms[d] * m_PrefixTransforms[d]);
  }
  PointType GetPrefixTransformedPosition(unsigned long int k, unsigned int d = 0) const {
    return this->TransformPoint(m_Positions[d]->operator[](k), m_PrefixTransforms[d]);
  }

  void SplitAllParticles(double epsilon);
  void SplitParticle(double epsilon, unsigned int idx, unsigned int d = 0);
  void AdvancedAllParticleSplitting(double epsilon, unsigned int domains_per_shape, unsigned int dom_to_process);
  // Debug function
  void PrintParticleSystem();

  void SetNeighborhood(unsigned int, NeighborhoodType *);
  void SetNeighborhood(NeighborhoodType *n) { this->SetNeighborhood(0, n); }
  NeighborhoodType::ConstPointer GetNeighborhood(unsigned int k) const { return m_Neighborhoods[k]; }

  inline PointVectorType FindNeighborhoodPoints(const PointType &p, int idx, double r, unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(p, idx, r);
  }
  inline PointVectorType FindNeighborhoodPoints(const PointType &p, int idx, std::vector<double> &w,
                                                std::vector<double> &distances, double r, unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(p, idx, w, distances, r);
  }
  inline PointVectorType FindNeighborhoodPoints(const PointType &p, int idx, std::vector<double> &w, double r,
                                                unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(p, idx, w, r);
  }
  inline PointVectorType FindNeighborhoodPoints(unsigned int idx, double r, unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(this->GetPosition(idx, d), idx, r);
  }
  inline PointVectorType FindNeighborhoodPoints(unsigned int idx, std::vector<double> &w,
                                                std::vector<double> &distances, double r, unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(this->GetPosition(idx, d), idx, w, distances, r);
  }
  inline PointVectorType FindNeighborhoodPoints(unsigned int idx, std::vector<double> &w, double r,
                                                unsigned int d = 0) const {
    return m_Neighborhoods[d]->FindNeighborhoodPoints(this->GetPosition(idx, d), idx, w, r);
  }

  //  inline int FindNeighborhoodPoints(const PointType &p,  double r, PointVectorType &vec, unsigned int d = 0) const
  //  {  return m_Neighborhoods[d]->FindNeighborhoodPoints(p, r, vec); }

  //   PointVectorType FindTransformedNeighborhoodPoints(const PointType &p, double r, unsigned int d = 0) const
  //   {
  //     PointVectorType ans = m_Neighborhoods[d]
  //       ->FindNeighborhoodPoints(this->TransformPoint(p, InverseTransform[d]), r);
  //     for (unsigned int i = 0; i < ans.size(); i++)
  //       {
  //       ans.Point[i] = this->TransformPoint(ans.Point[i], m_Transform[d]);
  //       }
  //     return ans;
  //   }

  void AddDomain(DomainType::Pointer input);

  std::vector<DomainType::Pointer>::const_iterator GetDomainsBegin() const { return m_Domains.begin(); }

  std::vector<DomainType::Pointer>::const_iterator GetDomainsEnd() const { return m_Domains.end(); }

  DomainType *GetDomain(unsigned int i) { return m_Domains[i].get(); }

  DomainType *GetDomain() { return m_Domains[0].get(); }

  const DomainType *GetDomain(unsigned int i) const { return m_Domains[i].get(); }

  const DomainType *GetDomain() const { return m_Domains[0].get(); }

  unsigned int GetNumberOfDomains() const { return m_Domains.size(); }

  void SetTransform(unsigned int i, const TransformType &);
  void SetTransform(const TransformType &p) { this->SetTransform(0, p); }
  void SetPrefixTransform(unsigned int i, const TransformType &);
  void SetPrefixTransform(const TransformType &p) { this->SetPrefixTransform(0, p); }

  std::vector<TransformType>::const_iterator GetTransformsBegin() const { return m_Transforms.begin(); }

  std::vector<TransformType>::const_iterator GetTransformsEnd() const { return m_Transforms.end(); }

  const TransformType &GetTransform(unsigned int i) const { return m_Transforms[i]; }

  const TransformType &GetTransform() const { return m_Transforms[0]; }

  TransformType GetTransform(unsigned int i) { return m_Transforms[i]; }

  TransformType GetTransform() { return m_Transforms[0]; }

  const TransformType &GetPrefixTransform(unsigned int i) const { return m_PrefixTransforms[i]; }

  const TransformType &GetPrefixTransform() const { return m_PrefixTransforms[0]; }

  TransformType GetPrefixTransform(unsigned int i) { return m_PrefixTransforms[i]; }

  TransformType GetPrefixTransform() { return m_PrefixTransforms[0]; }

  std::vector<TransformType>::const_iterator GetInverseTransformsBegin() const { return m_InverseTransforms.begin(); }

  std::vector<TransformType>::const_iterator GetInverseTransformsEnd() const { return m_InverseTransforms.end(); }

  const TransformType &GetInverseTransform(unsigned int i) const { return m_InverseTransforms[i]; }

  const TransformType &GetInverseTransform() const { return m_InverseTransforms[0]; }

  const TransformType &GetInversePrefixTransform(unsigned int i) const { return m_InversePrefixTransforms[i]; }

  const TransformType &GetInversePrefixTransform() const { return m_InversePrefixTransforms[0]; }

  const std::vector<PointContainerType::Pointer> &GetPositions() const { return m_Positions; }
  const PointContainerType::Pointer &GetPositions(unsigned int d) const { return m_Positions[d]; }

  void AddPositionList(const std::vector<PointType> &, unsigned int d = 0);

  PointType TransformPoint(const PointType &, const TransformType &) const;

  VectorType TransformVector(const VectorType &, const TransformType &) const;

  VnlMatrixType TransformNormalDerivative(const VnlMatrixType &, const TransformType &) const;

  inline TransformType InvertTransform(const TransformType &T) const {
    // Note, vnl_inverse is optimized for small matrices 1x1 - 4x4
    return vnl_inverse(T);
  }

  void FlagDomain(unsigned int i) {
    // ensure large enough
    while (i >= this->m_DomainFlags.size()) {
      m_DomainFlags.push_back(false);
    }

    // set the flag
    m_DomainFlags[i] = true;
  }
  void UnflagDomain(unsigned int i) { m_DomainFlags[i] = false; }
  bool GetDomainFlag(unsigned int i) const {
    if (i >= m_DomainFlags.size()) {
      // not set
      return false;
    }
    return m_DomainFlags[i];
  }
  const std::vector<bool> &GetDomainFlags() const { return m_DomainFlags; }
  void SetDomainFlags() {
    for (unsigned int i = 0; i < m_DomainFlags.size(); i++) {
      m_DomainFlags[i] = true;
    }
  }
  void ResetDomainFlags() {
    for (unsigned int i = 0; i < m_DomainFlags.size(); i++) {
      m_DomainFlags[i] = false;
    }
  }

  void SetFixedParticleFlag(unsigned int d, unsigned int i) { m_FixedParticleFlags[d][i] = true; }
  void ResetFixedParticleFlag(unsigned int d, unsigned int i) { m_FixedParticleFlags[d][i] = false; }
  bool GetFixedParticleFlag(unsigned int d, unsigned int i) const { return m_FixedParticleFlags[d][i]; }
  void ResetFixedParticleFlags() {
    for (unsigned d = 0; d < m_FixedParticleFlags.size(); d++) {
      for (unsigned int i = 0; i < m_FixedParticleFlags[d].size(); i++) m_FixedParticleFlags[d][i] = false;
    }
  }

  void SetDomainsPerShape(unsigned int num) {
    m_DomainsPerShape = num;
    m_FixedParticleFlags.resize(m_DomainsPerShape);
  }
  unsigned int GetDomainsPerShape() const { return m_DomainsPerShape; }

  void SetNumberOfDomains(unsigned int);

  // Returns the maximum distance between nearest neighbors in domain dom
  double ComputeMaxDistNearestNeighbors(size_t dom);

  void SetFieldAttributes(const std::vector<std::string> &field_attributes) { m_FieldAttributes = field_attributes; }

  const std::vector<std::string> &GetFieldAttributes() const { return m_FieldAttributes; }

 protected:
  ParticleSystem();
  void PrintSelf(std::ostream &os, itk::Indent indent) const;
  virtual ~ParticleSystem(){};

  TransformType &GetInverseTransform(unsigned int i) { return m_InverseTransforms[i]; }

  TransformType &GetInverseTransform() { return m_InverseTransforms[0]; }

  TransformType &GetInversePrefixTransform(unsigned int i) { return m_InversePrefixTransforms[i]; }

  TransformType &GetInversePrefixTransform() { return m_InversePrefixTransforms[0]; }

 private:
  ParticleSystem(const Self &);  // purposely not implemented
  void operator=(const Self &);  // purposely not implemented

  std::vector<PointContainerType::Pointer> m_Positions;

  std::vector<DomainType::Pointer> m_Domains;

  unsigned int m_DomainsPerShape;

  std::vector<NeighborhoodType::Pointer> m_Neighborhoods;

  std::vector<TransformType> m_Transforms;

  std::vector<TransformType> m_InverseTransforms;

  std::vector<TransformType> m_PrefixTransforms;

  std::vector<TransformType> m_InversePrefixTransforms;

  std::vector<unsigned long int> m_IndexCounters;

  std::vector<bool> m_DomainFlags;

  std::vector<std::vector<bool>> m_FixedParticleFlags;

  std::vector<std::string> m_FieldAttributes;

  std::mt19937 m_rand{42};
};

}  // end namespace shapeworks

Updated on 2024-03-17 at 12:58:44 -0600