Skip to content

Libs/Optimize/ParticleSystem/itkParticleGeneralShapeMatrix.h

Namespaces

Name
itk

Classes

Name
class itk::ParticleGeneralShapeMatrix
Each column describes a shape. A shape may be composed of m_DomainsPerShape domains (default 1). ALL DOMAINS ARE NOT ASSUMED TO HAVE THE SAME NUMBER OF PARTICLES!

Source code

#pragma once

#include "itkParticleAttribute.h"
#include "itkDataObject.h"
#include "itkWeakPointer.h"
#include "itkParticleContainer.h"
#include "vnl/vnl_matrix.h"

#include "ParticleImplicitSurfaceDomain.h"
#include "ParticleImageDomainWithGradients.h"
#include "TriMesh.h"

#include "itkParticleSystem.h"
namespace itk
{
template <class T, unsigned int VDimension>
class ITK_EXPORT ParticleGeneralShapeMatrix
        : public vnl_matrix<T>, public ParticleAttribute<VDimension>
{
public:
    typedef T DataType;
    typedef ParticleGeneralShapeMatrix Self;
    typedef ParticleAttribute<VDimension> Superclass;
    typedef SmartPointer<Self>  Pointer;
    typedef SmartPointer<const Self>  ConstPointer;
    typedef WeakPointer<const Self>  ConstWeakPointer;

    typedef ParticleSystem ParticleSystemType;

    itkNewMacro(Self)


    itkTypeMacro(ParticleGeneralShapeMatrix, ParticleAttribute)

    virtual void BeforeIteration() {}
    virtual void AfterIteration() {}

    void SetDomainsPerShape(int i)
    { m_DomainsPerShape = i;     }
    int GetDomainsPerShape() const
    { return m_DomainsPerShape;  }

    void SetAttributesPerDomain(const std::vector<int> &i)
    { m_AttributesPerDomain = i; }

    void SetAttributeScales( const std::vector<double> &s)
    { m_AttributeScales = s;     }

    void SetXYZ(int i, bool val)
    {
        if (m_use_xyz.size() != m_DomainsPerShape)
            m_use_xyz.resize(m_DomainsPerShape);
        m_use_xyz[i] = val;
    }
    void SetNormals(int i, bool val)
    {
        if (m_use_normals.size() != m_DomainsPerShape)
            m_use_normals.resize(m_DomainsPerShape);
        m_use_normals[i] = val;
    }

    virtual void SetMatrix(const vnl_matrix<T> &m)
    {
        vnl_matrix<T>::operator=(m);
    }

    virtual void ResizeMatrix(int rs, int cs)
    {
        vnl_matrix<T> tmp(*this); // copy existing  matrix

        // Create new column (shape)
        this->set_size(rs, cs);

        // Copy old data into new matrix.
        for (unsigned int c = 0; c < tmp.cols(); c++)
        {
            for (unsigned int r = 0; r < tmp.rows(); r++)
                this->operator()(r,c) = tmp(r,c);
        }
    }

    virtual void DomainAddEventCallback(Object *, const EventObject &e)
    {
        const itk::ParticleDomainAddEvent &event = dynamic_cast<const itk::ParticleDomainAddEvent &>(e);
        unsigned int d = event.GetDomainIndex();

        if ( d % m_DomainsPerShape  == 0 )
            this->ResizeMatrix(this->rows(), this->cols()+1);
    }

    void SetValues(const ParticleSystemType *ps, int idx, int d)
    {
        const typename ParticleSystemType::PointType pos = ps->GetTransformedPosition(idx, d);
        const typename ParticleSystemType::PointType posLocal = ps->GetPosition(idx, d);
        unsigned int k = 0;
        int dom = d % m_DomainsPerShape;
        int num = 0;
        for (int i = 0; i < dom; i++)
        {
            if (m_use_xyz[i])
            {
                k += VDimension * ps->GetNumberOfParticles(i);
                num += VDimension;
            }
            if (m_use_normals[i])
            {
                k += VDimension * ps->GetNumberOfParticles(i);
                num += VDimension;
            }
            k += m_AttributesPerDomain[i]* ps->GetNumberOfParticles(i);
            num += m_AttributesPerDomain[i];
        }
        if (m_use_xyz[dom])
            k += idx * VDimension;
        if (m_use_normals[dom])
            k += idx * VDimension;
        k += idx * m_AttributesPerDomain[dom];

        int s = 0;
        if (m_use_xyz[dom])
        {
            for (unsigned int i = 0; i < VDimension; i++)
                this->operator()(i+k, d / m_DomainsPerShape) = pos[i]*m_AttributeScales[num+i+s];
            k += VDimension;
            s += VDimension;
        }
        if (m_use_normals[dom])
        {
            vnl_vector_fixed<float, DIMENSION> pN = ps->GetDomain(d)->SampleNormalAtPoint(posLocal, idx);
            typename ParticleSystemType::VectorType tmp;
            tmp[0] = pN[0]; tmp[1] = pN[1]; tmp[2] = pN[2];
            tmp = ps->TransformVector(tmp, ps->GetTransform(d) * ps->GetPrefixTransform(d));
            pN[0] = tmp[0]; pN[1] = tmp[1]; pN[2] = tmp[2];
            pN = pN.normalize(); // contains scaling
            for (unsigned int i = 0; i < VDimension; i++)
                this->operator()(i+k, d / m_DomainsPerShape) = pN[i]*m_AttributeScales[num+i+s];
            k += VDimension;
            s += VDimension;
        }

        std::vector<float> fVals;
        if (m_AttributesPerDomain[dom] > 0)
        {
          // TODO figure out what is going on here
            point pt;
            pt.clear();
            pt[0] = posLocal[0];
            pt[1] = posLocal[1];
            pt[2] = posLocal[2];
            fVals.clear();
            const shapeworks::ParticleImplicitSurfaceDomain<float> * domain = static_cast<const shapeworks::ParticleImplicitSurfaceDomain<float> *>(ps->GetDomain(d));
            meshFIM *ptr = domain->GetMesh();
            ptr->GetFeatureValues(pt, fVals);
            for (int aa = 0; aa < m_AttributesPerDomain[dom]; aa++)
                this->operator()(aa+k, d / m_DomainsPerShape) = fVals[aa]*m_AttributeScales[aa+num+s];
        }


    }

    virtual void PositionAddEventCallback(Object *o, const EventObject &e)
    {
        // update the size of matrix based on xyz, normals and number of attributes being used
        const ParticlePositionAddEvent &event = dynamic_cast<const ParticlePositionAddEvent &>(e);
        const ParticleSystemType *ps= dynamic_cast<const ParticleSystemType *>(o);
        const int d = event.GetDomainIndex();
        const unsigned int idx = event.GetPositionIndex();

        int numRows = 0;
        for (int i = 0; i < m_DomainsPerShape; i++)
        {
            if (m_use_xyz[i])
                numRows += VDimension * ps->GetNumberOfParticles(i);
            if (m_use_normals[i])
                numRows += VDimension * ps->GetNumberOfParticles(i);
             numRows += m_AttributesPerDomain[i]* ps->GetNumberOfParticles(i);
        }

        if (numRows > this->rows())
            this->ResizeMatrix(numRows, this->cols());

        this->SetValues(ps, idx, d);
    }

    virtual void PositionSetEventCallback(Object *o, const EventObject &e)
    {
        // update xyz, normals and number of attributes being used
        const ParticlePositionSetEvent &event = dynamic_cast<const ParticlePositionSetEvent &>(e);
        const ParticleSystemType *ps= dynamic_cast<const ParticleSystemType *>(o);
        const int d = event.GetDomainIndex();
        const unsigned int idx = event.GetPositionIndex();

        this->SetValues(ps, idx, d);
    }

    virtual void PositionRemoveEventCallback(Object *, const EventObject &)
    {
        // NEED TO IMPLEMENT THIS
    }

    void PrintMatrix()
    {
      std::cout << std::endl;
      for (unsigned int r = 0; r < this->rows(); r++)
        {
        for (unsigned int c = 0; c < this->cols(); c++)
          {
          std::cout << this->operator()(r, c) << "  ";
          }
      std::cout << std::endl;
        }
    }

    bool CheckForNans()
    {
      bool flag = false;
      for (unsigned int r = 0; r < this->rows(); r++)
        {
        for (unsigned int c = 0; c < this->cols(); c++)
          {
          if (isnan(this->operator()(r, c)))
          {
              flag = true;
              break;
          }
          }
        }
      return flag;
    }

protected:
        ParticleGeneralShapeMatrix()
    {
        m_DomainsPerShape = 1;

        this->m_DefinedCallbacks.DomainAddEvent = true;
        this->m_DefinedCallbacks.PositionAddEvent = true;
        this->m_DefinedCallbacks.PositionSetEvent = true;
        this->m_DefinedCallbacks.PositionRemoveEvent = true;
    }
    virtual ~ParticleGeneralShapeMatrix() {}

    void PrintSelf(std::ostream& os, Indent indent) const
    {  Superclass::PrintSelf(os,indent);  }

    int m_DomainsPerShape;
private:

    ParticleGeneralShapeMatrix(const Self&); //purposely not implemented
    void operator=(const Self&); //purposely not implemented

    std::vector<bool> m_use_xyz;
    std::vector<bool> m_use_normals;
    std::vector<int> m_AttributesPerDomain;
    std::vector<double> m_AttributeScales;

}; // end class

} // end namespace

Updated on 2022-07-23 at 17:50:04 -0600