<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkIpPic.h"
#include "mitkPixelType.h"
#include <itkVector.h>
#include <itkRGBPixel.h>
#include <itkRGBAPixel.h>
#include <itkCovariantVector.h>
#include "itkDiffusionTensor3D.h"

#define HUNDRED_VECS(HUN)   \
  TEN_VECS(HUN)                \
  TEN_VECS(HUN+10)             \
  TEN_VECS(HUN+20)             \
  TEN_VECS(HUN+30)             \
  TEN_VECS(HUN+40)             \
  TEN_VECS(HUN+50)             \
  TEN_VECS(HUN+60)             \
  TEN_VECS(HUN+70)             \
  TEN_VECS(HUN+80)             \
  TEN_VECS(HUN+90)             \

#define TEN_VECS(TEN)   \
  if(false){}               \
  N_VEC(TEN+ 1)                \
  N_VEC(TEN+ 2)             \
  N_VEC(TEN+ 3)             \
  N_VEC(TEN+ 4)             \
  N_VEC(TEN+ 5)             \
  N_VEC(TEN+ 6)             \
  N_VEC(TEN+ 7)             \
  N_VEC(TEN+ 8)             \
  N_VEC(TEN+ 9)             \
  N_VEC(TEN+10)             \

#define N_VEC(N_DIRS)       \
  _N_VEC(N_DIRS,double)     \
  _N_VEC(N_DIRS,float)      \

#define _N_VEC(N_DIRS,PIXTYPE)                                                          \
  else if ( *m_TypeId == typeid( itk::Vector<PIXTYPE,N_DIRS> ))  \
  {                                                                                \
  found = true;                                                                      \
  m_TypeId = & typeid( PIXTYPE );                                                    \
  m_NumberOfComponents *= N_DIRS;                                                \
  m_Type = mitkIpPicFloat;                                                               \
  m_Bpe = sizeof(PIXTYPE) * 8 * m_NumberOfComponents;                                \
  m_ItkTypeId = &typeid( itk::Vector<PIXTYPE,N_DIRS> );     \
  }                                                                                \

mitk::PixelType::PixelType() : m_TypeId( NULL ), m_Type( mitkIpPicUnknown ), m_Bpe( 0 ), m_NumberOfComponents( 1 )
{

}

mitk::PixelType::PixelType( const mitk::PixelType& aPixelType )
{
  Initialize( *aPixelType.GetTypeId(), aPixelType.GetNumberOfComponents() );
}

mitk::PixelType::PixelType( const std::type_info& aTypeId, int numberOfComponents, ItkIOPixelType anItkIoPixelType ) : m_TypeId( &aTypeId ), m_NumberOfComponents( numberOfComponents )
{
  Initialize( aTypeId, numberOfComponents, anItkIoPixelType );
}

mitk::PixelType::PixelType( mitkIpPicType_t type, int bpe, int numberOfComponents ) : m_Type( type ), m_Bpe( bpe ), m_NumberOfComponents( numberOfComponents )
{
  Initialize( type, bpe, numberOfComponents );
}

mitk::PixelType::PixelType( const mitkIpPicDescriptor* pic ) : m_NumberOfComponents( 1 )
{
   if ( pic != NULL )
      Initialize( pic->type, pic->bpe );
   else
   {
      m_TypeId = NULL;
      //  itkExceptionMacro("pic.IsNull() has no pixel type.");
   }
}

bool mitk::PixelType::operator==(const mitk::PixelType& rhs) const
{
  LOG_INFO << "operator==" << std::endl;

LOG_INFO << "m_Type = " << m_Type << " " << rhs.m_Type << std::endl;
LOG_INFO << "m_Bpe = " << m_Bpe << " " << rhs.m_Bpe << std::endl;
LOG_INFO << "m_NumberOfComponents = " << m_NumberOfComponents << " " << rhs.m_NumberOfComponents << std::endl;
LOG_INFO << "m_BitsPerComponent = " << m_BitsPerComponent << " " << rhs.m_BitsPerComponent << std::endl;

   return (
     *(this->m_TypeId) == *(rhs.m_TypeId)
    && this->m_Type == rhs.m_Type
    && this->m_Bpe == rhs.m_Bpe
    && this->m_NumberOfComponents == rhs.m_NumberOfComponents
    && this->m_BitsPerComponent == rhs.m_BitsPerComponent
    );
}

bool mitk::PixelType::operator!=(const mitk::PixelType& rhs) const
{
  return !(this->operator==(rhs));
}

bool mitk::PixelType::operator==(const std::type_info& typeId) const
{
  if (GetItkTypeId() == NULL)
    return false;
  return (*GetItkTypeId() == typeId);
}

bool mitk::PixelType::operator!=(const std::type_info& typeId) const
{
  return !(this->operator==(typeId));
}

#define SET_ITK_TYPE_ID(anItkIoPixelType_test, numberOfComponents_test, ITK_TYPE)     \
  if ( (itk::ImageIOBase::anItkIoPixelType_test == anItkIoPixelType ) &&              \
       (numberOfComponents_test == m_NumberOfComponents)                              \
     )                                                                                \
  {                                                                                \
    m_ItkTypeId = &typeid(ITK_TYPE);                                                  \
  }

#define SET_TYPE(TYPE, IPPIC_TYPE)                                                    \
  if ( *m_TypeId == typeid( TYPE ) )                                                  \
  {                                                                                \
    m_Type = IPPIC_TYPE;                                                              \
    m_Bpe = sizeof(TYPE) * 8 * m_NumberOfComponents;                                  \
                                                                                \
    typedef itk::Vector<TYPE, 3> Vector3Type;                                         \
    typedef itk::CovariantVector<TYPE, 3> CovariantVector3Type;                       \
    typedef itk::Point<TYPE, 3> Point3Type;                                           \
    typedef itk::Vector<TYPE, 2> Vector2Type;                                         \
    typedef itk::CovariantVector<TYPE, 2> CovariantVector2Type;                       \
    typedef itk::Point<TYPE, 2> Point2Type;                                           \
                                                                                \
    SET_ITK_TYPE_ID(UNKNOWNPIXELTYPE, 1, TYPE ) else                                  \
    SET_ITK_TYPE_ID(SCALAR, 1, TYPE ) else                                            \
                                                                                \
    SET_ITK_TYPE_ID(VECTOR, 2, Vector2Type ) else                                     \
    SET_ITK_TYPE_ID(COVARIANTVECTOR, 2, CovariantVector2Type ) else                   \
    SET_ITK_TYPE_ID(POINT, 2, Point2Type ) else                                       \
                                                                                \
    SET_ITK_TYPE_ID(RGB, 3, itk::RGBPixel<TYPE> ) else                                \
    /*SET_ITK_TYPE_ID(DIFFUSIONTENSOR3D, 6, itk::DiffusionTensor3D<TYPE> ) else */    \
    SET_ITK_TYPE_ID(VECTOR, 3, Vector3Type ) else                                     \
    SET_ITK_TYPE_ID(COVARIANTVECTOR, 3, CovariantVector3Type ) else                   \
    SET_ITK_TYPE_ID(POINT, 3, Point3Type ) else                                       \
                                                                                \
    SET_ITK_TYPE_ID(RGBA, 4, itk::RGBAPixel<TYPE> ) else                              \
    {                                                                                \
    }                                                                                \
  }                                                                                \
  else

void mitk::PixelType::Initialize( const std::type_info& aTypeId, int numberOfComponents, ItkIOPixelType anItkIoPixelType )
{
   m_TypeId = &aTypeId;
   m_NumberOfComponents = numberOfComponents;
   if(m_NumberOfComponents == 1)
     m_ItkTypeId = &aTypeId;
   else
     m_ItkTypeId = NULL;
   SET_TYPE(double, mitkIpPicFloat)
   SET_TYPE(float, mitkIpPicFloat)
   SET_TYPE(long, mitkIpPicInt)
   SET_TYPE(unsigned long, mitkIpPicUInt)
   SET_TYPE(int, mitkIpPicInt)
   SET_TYPE(unsigned int, mitkIpPicUInt)
   SET_TYPE(short, mitkIpPicInt)
   SET_TYPE(unsigned short, mitkIpPicUInt)
   SET_TYPE(char, mitkIpPicInt)
   SET_TYPE(unsigned char, mitkIpPicUInt)

   if ( *m_TypeId == typeid( itk::DiffusionTensor3D<float> ) )
   {
     m_TypeId = & typeid( float );
     m_NumberOfComponents *= 6;
     m_Type = mitkIpPicFloat;
     m_Bpe = sizeof(float) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::DiffusionTensor3D<float> );
   }
   else if ( *m_TypeId == typeid( itk::DiffusionTensor3D<double> ) )
   {
     m_TypeId = & typeid( double );
     m_NumberOfComponents *= 6;
     m_Type = mitkIpPicFloat;
     m_Bpe = sizeof(double) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::DiffusionTensor3D<double> );
   }
   else if ( *m_TypeId == typeid( itk::RGBPixel<unsigned char> ) )
   {
     m_Type = mitkIpPicUInt;
     m_NumberOfComponents = 3;
     m_Bpe = sizeof(unsigned char) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::RGBPixel<unsigned char> );
   }
   else if ( *m_TypeId == typeid( itk::RGBAPixel<unsigned char> ) )
   {
     itkExceptionMacro( "Pixel type currently not supported." );
   }
   else
   {
     bool found = false;

     // the following lines allow for fixed-size vector images up to a certain size limit
     // (commented out for shorter compile times)
     //HUNDRED_VECS(000)
     //HUNDRED_VECS(100)
     //HUNDRED_VECS(200)
     //HUNDRED_VECS(300)
     //HUNDRED_VECS(400)
     //HUNDRED_VECS(500)
     //HUNDRED_VECS(600)
     //HUNDRED_VECS(700)

     // allow for fixed-size vectors of specific length
     // (inspired by itkPointshell.cpp, precompiled q-ball configs)
     //TEN_VECS(0)
     //N_VEC(11)
     //N_VEC(12)
     if(false){}
     N_VEC(3)
     N_VEC(6)
     N_VEC(42)
     N_VEC(92)
     N_VEC(162)
     N_VEC(252)
     N_VEC(362)
     //N_VEC(492)
     //N_VEC(642)
     //N_VEC(812)
     //N_VEC(1002)

     if(!found)
       itkExceptionMacro( "Pixel type currently not supported." );
   }
   m_BitsPerComponent = m_Bpe / m_NumberOfComponents;
}

void mitk::PixelType::Initialize( mitkIpPicType_t type, int bpe, int numberOfComponents )
{
   m_Type = type;
   m_Bpe = bpe;
   m_NumberOfComponents = numberOfComponents;
   switch ( type )
   {
   case mitkIpPicUnknown:
      m_TypeId = &typeid( void* );
      break;
   case mitkIpPicBool:
      m_TypeId = &typeid( bool );
      m_Bpe = sizeof(bool) * 8 * numberOfComponents;
      break;
   case mitkIpPicASCII:
      m_TypeId = &typeid( char );
      m_Bpe = sizeof(char) * 8 * numberOfComponents;
      break;
   case mitkIpPicInt:
      switch ( bpe / numberOfComponents )
      {
      case 8:
         m_TypeId = &typeid( char );
         break;
      case 16:
         m_TypeId = &typeid( short );
         break;
      case 32:
         m_TypeId = &typeid( int );
         break;
      case 64:
         m_TypeId = &typeid( long );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicUInt:
      switch ( bpe / numberOfComponents )
      {
      case 8:
         m_TypeId = &typeid( unsigned char );
         break;
      case 16:
         m_TypeId = &typeid( unsigned short );
         break;
      case 24:
         m_TypeId = &typeid( unsigned char );
         m_NumberOfComponents = numberOfComponents = 3;
         break;
      case 32:
         m_TypeId = &typeid( unsigned int );
         break;
      case 64:
         m_TypeId = &typeid( unsigned long );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicFloat:
      switch ( bpe / numberOfComponents )
      {
      case 32:
         m_TypeId = &typeid( float );
         break;
      case 64:
         m_TypeId = &typeid( double );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicNonUniform:
      m_TypeId = &typeid( void* );
      break;
   case mitkIpPicTSV:
      m_TypeId = &typeid( void* );
      break;
   default:
      m_TypeId = NULL;
      itkExceptionMacro( "Pixel type currently not supported." );
      break;
   }
   m_BitsPerComponent = m_Bpe / numberOfComponents;

   if(m_NumberOfComponents == 1)
     m_ItkTypeId = m_TypeId;
   else
     m_ItkTypeId = NULL;
}

std::string mitk::PixelType::GetItkTypeAsString() const
{
  if (GetItkTypeId()==NULL)
  {
    return "unknown";
  }
  else
  {
    return GetItkTypeId()->name();
  }
}
<commit_msg>FIX (#2893): added additional vector sizes<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html 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 notices for more information.

=========================================================================*/

#include "mitkIpPic.h"
#include "mitkPixelType.h"
#include <itkVector.h>
#include <itkRGBPixel.h>
#include <itkRGBAPixel.h>
#include <itkCovariantVector.h>
#include "itkDiffusionTensor3D.h"

#define HUNDRED_VECS(HUN)   \
  TEN_VECS(HUN)                \
  TEN_VECS(HUN+10)             \
  TEN_VECS(HUN+20)             \
  TEN_VECS(HUN+30)             \
  TEN_VECS(HUN+40)             \
  TEN_VECS(HUN+50)             \
  TEN_VECS(HUN+60)             \
  TEN_VECS(HUN+70)             \
  TEN_VECS(HUN+80)             \
  TEN_VECS(HUN+90)             \

#define TEN_VECS(TEN)   \
  if(false){}               \
  N_VEC(TEN+ 1)                \
  N_VEC(TEN+ 2)             \
  N_VEC(TEN+ 3)             \
  N_VEC(TEN+ 4)             \
  N_VEC(TEN+ 5)             \
  N_VEC(TEN+ 6)             \
  N_VEC(TEN+ 7)             \
  N_VEC(TEN+ 8)             \
  N_VEC(TEN+ 9)             \
  N_VEC(TEN+10)             \

#define N_VEC(N_DIRS)       \
  _N_VEC(N_DIRS,double)     \
  _N_VEC(N_DIRS,float)      \

#define _N_VEC(N_DIRS,PIXTYPE)                                                          \
  else if ( *m_TypeId == typeid( itk::Vector<PIXTYPE,N_DIRS> ))  \
  {                                                                                \
  found = true;                                                                      \
  m_TypeId = & typeid( PIXTYPE );                                                    \
  m_NumberOfComponents *= N_DIRS;                                                \
  m_Type = mitkIpPicFloat;                                                               \
  m_Bpe = sizeof(PIXTYPE) * 8 * m_NumberOfComponents;                                \
  m_ItkTypeId = &typeid( itk::Vector<PIXTYPE,N_DIRS> );     \
  }                                                                                \

mitk::PixelType::PixelType() : m_TypeId( NULL ), m_Type( mitkIpPicUnknown ), m_Bpe( 0 ), m_NumberOfComponents( 1 )
{

}

mitk::PixelType::PixelType( const mitk::PixelType& aPixelType )
{
  Initialize( *aPixelType.GetTypeId(), aPixelType.GetNumberOfComponents() );
}

mitk::PixelType::PixelType( const std::type_info& aTypeId, int numberOfComponents, ItkIOPixelType anItkIoPixelType ) : m_TypeId( &aTypeId ), m_NumberOfComponents( numberOfComponents )
{
  Initialize( aTypeId, numberOfComponents, anItkIoPixelType );
}

mitk::PixelType::PixelType( mitkIpPicType_t type, int bpe, int numberOfComponents ) : m_Type( type ), m_Bpe( bpe ), m_NumberOfComponents( numberOfComponents )
{
  Initialize( type, bpe, numberOfComponents );
}

mitk::PixelType::PixelType( const mitkIpPicDescriptor* pic ) : m_NumberOfComponents( 1 )
{
   if ( pic != NULL )
      Initialize( pic->type, pic->bpe );
   else
   {
      m_TypeId = NULL;
      //  itkExceptionMacro("pic.IsNull() has no pixel type.");
   }
}

bool mitk::PixelType::operator==(const mitk::PixelType& rhs) const
{
  LOG_INFO << "operator==" << std::endl;

LOG_INFO << "m_Type = " << m_Type << " " << rhs.m_Type << std::endl;
LOG_INFO << "m_Bpe = " << m_Bpe << " " << rhs.m_Bpe << std::endl;
LOG_INFO << "m_NumberOfComponents = " << m_NumberOfComponents << " " << rhs.m_NumberOfComponents << std::endl;
LOG_INFO << "m_BitsPerComponent = " << m_BitsPerComponent << " " << rhs.m_BitsPerComponent << std::endl;

   return (
     *(this->m_TypeId) == *(rhs.m_TypeId)
    && this->m_Type == rhs.m_Type
    && this->m_Bpe == rhs.m_Bpe
    && this->m_NumberOfComponents == rhs.m_NumberOfComponents
    && this->m_BitsPerComponent == rhs.m_BitsPerComponent
    );
}

bool mitk::PixelType::operator!=(const mitk::PixelType& rhs) const
{
  return !(this->operator==(rhs));
}

bool mitk::PixelType::operator==(const std::type_info& typeId) const
{
  if (GetItkTypeId() == NULL)
    return false;
  return (*GetItkTypeId() == typeId);
}

bool mitk::PixelType::operator!=(const std::type_info& typeId) const
{
  return !(this->operator==(typeId));
}

#define SET_ITK_TYPE_ID(anItkIoPixelType_test, numberOfComponents_test, ITK_TYPE)     \
  if ( (itk::ImageIOBase::anItkIoPixelType_test == anItkIoPixelType ) &&              \
       (numberOfComponents_test == m_NumberOfComponents)                              \
     )                                                                                \
  {                                                                                \
    m_ItkTypeId = &typeid(ITK_TYPE);                                                  \
  }

#define SET_TYPE(TYPE, IPPIC_TYPE)                                                    \
  if ( *m_TypeId == typeid( TYPE ) )                                                  \
  {                                                                                \
    m_Type = IPPIC_TYPE;                                                              \
    m_Bpe = sizeof(TYPE) * 8 * m_NumberOfComponents;                                  \
                                                                                \
    typedef itk::Vector<TYPE, 3> Vector3Type;                                         \
    typedef itk::CovariantVector<TYPE, 3> CovariantVector3Type;                       \
    typedef itk::Point<TYPE, 3> Point3Type;                                           \
    typedef itk::Vector<TYPE, 2> Vector2Type;                                         \
    typedef itk::CovariantVector<TYPE, 2> CovariantVector2Type;                       \
    typedef itk::Point<TYPE, 2> Point2Type;                                           \
                                                                                \
    SET_ITK_TYPE_ID(UNKNOWNPIXELTYPE, 1, TYPE ) else                                  \
    SET_ITK_TYPE_ID(SCALAR, 1, TYPE ) else                                            \
                                                                                \
    SET_ITK_TYPE_ID(VECTOR, 2, Vector2Type ) else                                     \
    SET_ITK_TYPE_ID(COVARIANTVECTOR, 2, CovariantVector2Type ) else                   \
    SET_ITK_TYPE_ID(POINT, 2, Point2Type ) else                                       \
                                                                                \
    SET_ITK_TYPE_ID(RGB, 3, itk::RGBPixel<TYPE> ) else                                \
    /*SET_ITK_TYPE_ID(DIFFUSIONTENSOR3D, 6, itk::DiffusionTensor3D<TYPE> ) else */    \
    SET_ITK_TYPE_ID(VECTOR, 3, Vector3Type ) else                                     \
    SET_ITK_TYPE_ID(COVARIANTVECTOR, 3, CovariantVector3Type ) else                   \
    SET_ITK_TYPE_ID(POINT, 3, Point3Type ) else                                       \
                                                                                \
    SET_ITK_TYPE_ID(RGBA, 4, itk::RGBAPixel<TYPE> ) else                              \
    {                                                                                \
    }                                                                                \
  }                                                                                \
  else

void mitk::PixelType::Initialize( const std::type_info& aTypeId, int numberOfComponents, ItkIOPixelType anItkIoPixelType )
{
   m_TypeId = &aTypeId;
   m_NumberOfComponents = numberOfComponents;
   if(m_NumberOfComponents == 1)
     m_ItkTypeId = &aTypeId;
   else
     m_ItkTypeId = NULL;
   SET_TYPE(double, mitkIpPicFloat)
   SET_TYPE(float, mitkIpPicFloat)
   SET_TYPE(long, mitkIpPicInt)
   SET_TYPE(unsigned long, mitkIpPicUInt)
   SET_TYPE(int, mitkIpPicInt)
   SET_TYPE(unsigned int, mitkIpPicUInt)
   SET_TYPE(short, mitkIpPicInt)
   SET_TYPE(unsigned short, mitkIpPicUInt)
   SET_TYPE(char, mitkIpPicInt)
   SET_TYPE(unsigned char, mitkIpPicUInt)

   if ( *m_TypeId == typeid( itk::DiffusionTensor3D<float> ) )
   {
     m_TypeId = & typeid( float );
     m_NumberOfComponents *= 6;
     m_Type = mitkIpPicFloat;
     m_Bpe = sizeof(float) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::DiffusionTensor3D<float> );
   }
   else if ( *m_TypeId == typeid( itk::DiffusionTensor3D<double> ) )
   {
     m_TypeId = & typeid( double );
     m_NumberOfComponents *= 6;
     m_Type = mitkIpPicFloat;
     m_Bpe = sizeof(double) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::DiffusionTensor3D<double> );
   }
   else if ( *m_TypeId == typeid( itk::RGBPixel<unsigned char> ) )
   {
     m_Type = mitkIpPicUInt;
     m_NumberOfComponents = 3;
     m_Bpe = sizeof(unsigned char) * 8 * m_NumberOfComponents;
     m_ItkTypeId = &typeid( itk::RGBPixel<unsigned char> );
   }
   else if ( *m_TypeId == typeid( itk::RGBAPixel<unsigned char> ) )
   {
     itkExceptionMacro( "Pixel type currently not supported." );
   }
   else
   {
     bool found = false;

     // the following lines allow for fixed-size vector images up to a certain size limit
     // (commented out for shorter compile times)
     //HUNDRED_VECS(000)
     //HUNDRED_VECS(100)
     //HUNDRED_VECS(200)
     //HUNDRED_VECS(300)
     //HUNDRED_VECS(400)
     //HUNDRED_VECS(500)
     //HUNDRED_VECS(600)
     //HUNDRED_VECS(700)

     // allow for fixed-size vectors of specific length
     // (inspired by itkPointshell.cpp, precompiled q-ball configs)
     //TEN_VECS(0)
     //N_VEC(11)
     //N_VEC(12)
     if(false){}
     N_VEC(3)
     N_VEC(6)
     N_VEC(42)
     N_VEC(92)
     N_VEC(162)
     N_VEC(252)
     N_VEC(362)
     N_VEC(492)
     N_VEC(642)
     N_VEC(812)
     N_VEC(1002)

     if(!found)
       itkExceptionMacro( "Pixel type currently not supported." );
   }
   m_BitsPerComponent = m_Bpe / m_NumberOfComponents;
}

void mitk::PixelType::Initialize( mitkIpPicType_t type, int bpe, int numberOfComponents )
{
   m_Type = type;
   m_Bpe = bpe;
   m_NumberOfComponents = numberOfComponents;
   switch ( type )
   {
   case mitkIpPicUnknown:
      m_TypeId = &typeid( void* );
      break;
   case mitkIpPicBool:
      m_TypeId = &typeid( bool );
      m_Bpe = sizeof(bool) * 8 * numberOfComponents;
      break;
   case mitkIpPicASCII:
      m_TypeId = &typeid( char );
      m_Bpe = sizeof(char) * 8 * numberOfComponents;
      break;
   case mitkIpPicInt:
      switch ( bpe / numberOfComponents )
      {
      case 8:
         m_TypeId = &typeid( char );
         break;
      case 16:
         m_TypeId = &typeid( short );
         break;
      case 32:
         m_TypeId = &typeid( int );
         break;
      case 64:
         m_TypeId = &typeid( long );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicUInt:
      switch ( bpe / numberOfComponents )
      {
      case 8:
         m_TypeId = &typeid( unsigned char );
         break;
      case 16:
         m_TypeId = &typeid( unsigned short );
         break;
      case 24:
         m_TypeId = &typeid( unsigned char );
         m_NumberOfComponents = numberOfComponents = 3;
         break;
      case 32:
         m_TypeId = &typeid( unsigned int );
         break;
      case 64:
         m_TypeId = &typeid( unsigned long );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicFloat:
      switch ( bpe / numberOfComponents )
      {
      case 32:
         m_TypeId = &typeid( float );
         break;
      case 64:
         m_TypeId = &typeid( double );
         break;
      default:
         m_TypeId = NULL;
         itkExceptionMacro( "Pixel type currently not supported." );
      }
      break;
   case mitkIpPicNonUniform:
      m_TypeId = &typeid( void* );
      break;
   case mitkIpPicTSV:
      m_TypeId = &typeid( void* );
      break;
   default:
      m_TypeId = NULL;
      itkExceptionMacro( "Pixel type currently not supported." );
      break;
   }
   m_BitsPerComponent = m_Bpe / numberOfComponents;

   if(m_NumberOfComponents == 1)
     m_ItkTypeId = m_TypeId;
   else
     m_ItkTypeId = NULL;
}

std::string mitk::PixelType::GetItkTypeAsString() const
{
  if (GetItkTypeId()==NULL)
  {
    return "unknown";
  }
  else
  {
    return GetItkTypeId()->name();
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix build error...<commit_after><|endoftext|>


<commit_before>#include "Color.h"
#include "Quaternion.h"
#include "Transform.h"
#include "Vector3D.h"
#include "Matrix4.h"

#include <QScriptEngine>
#include <QColor>
#include <QVector3D>
#include <QQuaternion>

QScriptValue toScriptValueColor(QScriptEngine *engine, const Color &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("r", QScriptValue(engine, s.r));
    obj.setProperty("g", QScriptValue(engine, s.g));
    obj.setProperty("b", QScriptValue(engine, s.b));
    obj.setProperty("a", QScriptValue(engine, s.a));
    return obj;
}

void fromScriptValueColor(const QScriptValue &obj, Color &s)
{
    s.r = (float)obj.property("r").toNumber();
    s.g = (float)obj.property("g").toNumber();
    s.b = (float)obj.property("b").toNumber();
    s.a = (float)obj.property("a").toNumber();
}

QScriptValue toScriptValueQColor(QScriptEngine *engine, const QColor &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("r", QScriptValue(engine, s.red()));
    obj.setProperty("g", QScriptValue(engine, s.green()));
    obj.setProperty("b", QScriptValue(engine, s.blue()));
    obj.setProperty("a", QScriptValue(engine, s.alpha()));
    return obj;
}

void fromScriptValueQColor(const QScriptValue &obj, QColor &s)
{
    s.setRed((float)obj.property("r").toNumber());
    s.setGreen((float)obj.property("g").toNumber());
    s.setBlue((float)obj.property("b").toNumber());
    s.setAlpha((float)obj.property("a").toNumber());
}

QScriptValue toScriptValueVector3(QScriptEngine *engine, const Vector3df &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x));
    obj.setProperty("y", QScriptValue(engine, s.y));
    obj.setProperty("z", QScriptValue(engine, s.z));
    return obj;
}

void fromScriptValueVector3(const QScriptValue &obj, Vector3df &s)
{
    s.x = (float)obj.property("x").toNumber();
    s.y = (float)obj.property("y").toNumber();
    s.z = (float)obj.property("z").toNumber();
}

QScriptValue toScriptValueQVector3D(QScriptEngine *engine, const QVector3D &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x()));
    obj.setProperty("y", QScriptValue(engine, s.y()));
    obj.setProperty("z", QScriptValue(engine, s.z()));
    return obj;
}

void fromScriptValueQVector3D(const QScriptValue &obj, QVector3D &s)
{
    s.setX((float)obj.property("x").toNumber());
    s.setY((float)obj.property("y").toNumber());
    s.setZ((float)obj.property("z").toNumber());
}

QScriptValue toScriptValueQuaternion(QScriptEngine *engine, const Quaternion &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x));
    obj.setProperty("y", QScriptValue(engine, s.y));
    obj.setProperty("z", QScriptValue(engine, s.z));
    obj.setProperty("w", QScriptValue(engine, s.w));
    return obj;
}

void fromScriptValueQuaternion(const QScriptValue &obj, Quaternion &s)
{
    s.x = (float)obj.property("x").toNumber();
    s.y = (float)obj.property("y").toNumber();
    s.z = (float)obj.property("z").toNumber();
    s.w = (float)obj.property("w").toNumber();
}

QScriptValue toScriptValueQQuaternion(QScriptEngine *engine, const QQuaternion &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x()));
    obj.setProperty("y", QScriptValue(engine, s.y()));
    obj.setProperty("z", QScriptValue(engine, s.z()));
    obj.setProperty("w", QScriptValue(engine, s.scalar()));
    return obj;
}

void fromScriptValueQQuaternion(const QScriptValue &obj, QQuaternion &s)
{
    s.setX((float)obj.property("x").toNumber());
    s.setY((float)obj.property("y").toNumber());
    s.setZ((float)obj.property("z").toNumber());
    s.setScalar((float)obj.property("w").toNumber());
}

QScriptValue toScriptValueTransform(QScriptEngine *engine, const Transform &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("pos", toScriptValueVector3(engine, s.position));
    obj.setProperty("rot", toScriptValueVector3(engine, s.rotation));
    obj.setProperty("scale", toScriptValueVector3(engine, s.scale));
    return obj;
}

void fromScriptValueTransform(const QScriptValue &obj, Transform &s)
{
    fromScriptValueVector3(obj.property("pos"), s.position);
    fromScriptValueVector3(obj.property("rot"), s.rotation);
    fromScriptValueVector3(obj.property("scale"), s.scale);
}

void RegisterNaaliCoreMetaTypes()
{
    qRegisterMetaType<Color>("Color");
    qRegisterMetaType<Vector3df>("Vector3df");
    qRegisterMetaType<Quaternion>("Quaternion");
    qRegisterMetaType<Transform>("Transform");
}

void ExposeNaaliCoreTypes(QScriptEngine *engine)
{
    qScriptRegisterMetaType(engine, toScriptValueColor, fromScriptValueColor);
    qScriptRegisterMetaType(engine, toScriptValueQColor, fromScriptValueQColor);
    qScriptRegisterMetaType(engine, toScriptValueVector3, fromScriptValueVector3);
    qScriptRegisterMetaType(engine, toScriptValueQVector3D, fromScriptValueQVector3D);
    qScriptRegisterMetaType(engine, toScriptValueQuaternion, fromScriptValueQuaternion);
    qScriptRegisterMetaType(engine, toScriptValueQQuaternion, fromScriptValueQQuaternion);
    qScriptRegisterMetaType(engine, toScriptValueTransform, fromScriptValueTransform);
}
<commit_msg>Fixed missing include stableheaders<commit_after>#include "StableHeaders.h"
#include "Color.h"
#include "Quaternion.h"
#include "Transform.h"
#include "Vector3D.h"
#include "Matrix4.h"

#include <QScriptEngine>
#include <QColor>
#include <QVector3D>
#include <QQuaternion>

QScriptValue toScriptValueColor(QScriptEngine *engine, const Color &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("r", QScriptValue(engine, s.r));
    obj.setProperty("g", QScriptValue(engine, s.g));
    obj.setProperty("b", QScriptValue(engine, s.b));
    obj.setProperty("a", QScriptValue(engine, s.a));
    return obj;
}

void fromScriptValueColor(const QScriptValue &obj, Color &s)
{
    s.r = (float)obj.property("r").toNumber();
    s.g = (float)obj.property("g").toNumber();
    s.b = (float)obj.property("b").toNumber();
    s.a = (float)obj.property("a").toNumber();
}

QScriptValue toScriptValueQColor(QScriptEngine *engine, const QColor &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("r", QScriptValue(engine, s.red()));
    obj.setProperty("g", QScriptValue(engine, s.green()));
    obj.setProperty("b", QScriptValue(engine, s.blue()));
    obj.setProperty("a", QScriptValue(engine, s.alpha()));
    return obj;
}

void fromScriptValueQColor(const QScriptValue &obj, QColor &s)
{
    s.setRed((float)obj.property("r").toNumber());
    s.setGreen((float)obj.property("g").toNumber());
    s.setBlue((float)obj.property("b").toNumber());
    s.setAlpha((float)obj.property("a").toNumber());
}

QScriptValue toScriptValueVector3(QScriptEngine *engine, const Vector3df &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x));
    obj.setProperty("y", QScriptValue(engine, s.y));
    obj.setProperty("z", QScriptValue(engine, s.z));
    return obj;
}

void fromScriptValueVector3(const QScriptValue &obj, Vector3df &s)
{
    s.x = (float)obj.property("x").toNumber();
    s.y = (float)obj.property("y").toNumber();
    s.z = (float)obj.property("z").toNumber();
}

QScriptValue toScriptValueQVector3D(QScriptEngine *engine, const QVector3D &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x()));
    obj.setProperty("y", QScriptValue(engine, s.y()));
    obj.setProperty("z", QScriptValue(engine, s.z()));
    return obj;
}

void fromScriptValueQVector3D(const QScriptValue &obj, QVector3D &s)
{
    s.setX((float)obj.property("x").toNumber());
    s.setY((float)obj.property("y").toNumber());
    s.setZ((float)obj.property("z").toNumber());
}

QScriptValue toScriptValueQuaternion(QScriptEngine *engine, const Quaternion &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x));
    obj.setProperty("y", QScriptValue(engine, s.y));
    obj.setProperty("z", QScriptValue(engine, s.z));
    obj.setProperty("w", QScriptValue(engine, s.w));
    return obj;
}

void fromScriptValueQuaternion(const QScriptValue &obj, Quaternion &s)
{
    s.x = (float)obj.property("x").toNumber();
    s.y = (float)obj.property("y").toNumber();
    s.z = (float)obj.property("z").toNumber();
    s.w = (float)obj.property("w").toNumber();
}

QScriptValue toScriptValueQQuaternion(QScriptEngine *engine, const QQuaternion &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("x", QScriptValue(engine, s.x()));
    obj.setProperty("y", QScriptValue(engine, s.y()));
    obj.setProperty("z", QScriptValue(engine, s.z()));
    obj.setProperty("w", QScriptValue(engine, s.scalar()));
    return obj;
}

void fromScriptValueQQuaternion(const QScriptValue &obj, QQuaternion &s)
{
    s.setX((float)obj.property("x").toNumber());
    s.setY((float)obj.property("y").toNumber());
    s.setZ((float)obj.property("z").toNumber());
    s.setScalar((float)obj.property("w").toNumber());
}

QScriptValue toScriptValueTransform(QScriptEngine *engine, const Transform &s)
{
    QScriptValue obj = engine->newObject();
    obj.setProperty("pos", toScriptValueVector3(engine, s.position));
    obj.setProperty("rot", toScriptValueVector3(engine, s.rotation));
    obj.setProperty("scale", toScriptValueVector3(engine, s.scale));
    return obj;
}

void fromScriptValueTransform(const QScriptValue &obj, Transform &s)
{
    fromScriptValueVector3(obj.property("pos"), s.position);
    fromScriptValueVector3(obj.property("rot"), s.rotation);
    fromScriptValueVector3(obj.property("scale"), s.scale);
}

void RegisterNaaliCoreMetaTypes()
{
    qRegisterMetaType<Color>("Color");
    qRegisterMetaType<Vector3df>("Vector3df");
    qRegisterMetaType<Quaternion>("Quaternion");
    qRegisterMetaType<Transform>("Transform");
}

void ExposeNaaliCoreTypes(QScriptEngine *engine)
{
    qScriptRegisterMetaType(engine, toScriptValueColor, fromScriptValueColor);
    qScriptRegisterMetaType(engine, toScriptValueQColor, fromScriptValueQColor);
    qScriptRegisterMetaType(engine, toScriptValueVector3, fromScriptValueVector3);
    qScriptRegisterMetaType(engine, toScriptValueQVector3D, fromScriptValueQVector3D);
    qScriptRegisterMetaType(engine, toScriptValueQuaternion, fromScriptValueQuaternion);
    qScriptRegisterMetaType(engine, toScriptValueQQuaternion, fromScriptValueQQuaternion);
    qScriptRegisterMetaType(engine, toScriptValueTransform, fromScriptValueTransform);
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  testInitState.cpp                         *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Peter Eastman, Ajay Seth                                        *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <stdint.h>
#include <OpenSim/Simulation/Manager/Manager.h>
#include <OpenSim/Simulation/Control/ControlSetController.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

//==============================================================================
// testInitState tests that a Model consistently generates the same default
// state from its initSystem() method. It also tests that when the properties
// are updated (after a simulation) that the defaults match the values in the
// new state.
//==============================================================================
void testStates(const string& modelFile);
//==============================================================================
// testMemoryUsage tests that repeated initialization of the state does not
// cause the memory footprint of the process to increase significantly.
//==============================================================================
void testMemoryUsage(const string& modelFile);

static const int MAX_N_TRIES = 100;

int main()
{
    try {
        LoadOpenSimLibrary("osimActuators");
        testStates("arm26.osim");
        testMemoryUsage("arm26.osim");
        testMemoryUsage("PushUpToesOnGroundWithMuscles.osim");
    }
    catch (const Exception& e) {
        cout << "testInitState failed: ";
        e.print(cout);
        return 1;
    }
    catch (const std::exception& e) {
        cout << "testInitState failed: " << e.what() << endl;
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}

//==============================================================================
// Test Cases
//==============================================================================
void testStates(const string& modelFile)
{
    using namespace SimTK;

    //==========================================================================
    // Setup OpenSim model
    Model model(modelFile);
    ControlSetController* controller = new ControlSetController();
    controller->setControlSetFileName("arm26_StaticOptimization_controls.xml");

    model.addController( controller );
    // original default state
    State& state = model.initSystem();

    // hold on to original default continuous state variables
    Vector y1 = state.getY();
    y1 = state.getY();
    //y1.dump("y1: Initial state:");

    // update state to contain muscle states that yield muscle equilibrium
    model.equilibrateMuscles(state);
    state.getY().dump("y1: State after equilibrateMuscles:");
    //==========================================================================
    // Compute the force and torque at the specified times.

    RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
    Manager manager(model, integrator);
    manager.setInitialTime(0.0);
    manager.setFinalTime(0.05);

    // update state after a short simulation forward in time
    manager.integrate(state);

    // continuous state variables after simulation
    Vector y2 = state.getY();
    //y2.dump("y2: State after integration:");

    // reset model working state to default state
    State& state2 = model.initializeState();

    // another version of default continuous state variables
    // should be unaffected by simulation of the system
    Vector y3 = state2.getY();
    //y3.dump("y3: Model reset to Initial state:");

    // update state to contain muscle states that yield muscle equilibrium
    model.equilibrateMuscles(state2);
    state.getY().dump("y3: State after equilibrateMuscles:");
    //==========================================================================
    // Compute the force and torque at the specified times.

    RungeKuttaMersonIntegrator integrator2(model.getMultibodySystem());
    Manager manager2(model, integrator);
    manager2.setInitialTime(0.0);
    manager2.setFinalTime(0.05);

    // update state after a short simulation forward in time
    manager2.integrate(state2);

    // get the default continuous state variables updated
    // from the state after the simulation
    Vector y4 = state2.getY();

    //y4.dump("y4: Default State after second simulation:");

    for (int i = 0; i < y1.size(); i++)
    {
        cout << i <<" : y1[i] = " << y1[i] << " :: y3[i] = " << y3[i] << endl;
        ASSERT_EQUAL(y1[i], y3[i], 1e-5,__FILE__, __LINE__,
            "Model failed to maintain default state after simulation.");
        cout << i <<" : y2[i] = " << y2[i] << " :: y4[i] = " << y4[i] << endl;
        ASSERT_EQUAL(y2[i], y4[i], 1e-5,__FILE__, __LINE__,
            "Model failed to properly update default state after simulation.");
    }
    ASSERT(max(abs(y1-y2)) > 1e-4);
}

void testMemoryUsage(const string& modelFile)
{
    using namespace SimTK;

    // Throw an exception if we cannot validate estimates
    // of memory with current instrumentation
    validateMemoryUseEstimates(20);

    //=========================================================================
    // Estimate the size of the model when loaded into memory
    auto creator = [modelFile]() {
        Model* model = new Model(modelFile);
        model->finalizeFromProperties();
        return model;
    };

    size_t model_size =
        estimateMemoryChangeForCreator<Model>(creator, 5);

    OPENSIM_THROW_IF(model_size == 0, OpenSim::Exception,
        "Model size was estimated to be zero.");

    Model model(modelFile);
    State& state = model.initSystem();

    // also time how long initializing the state takes
    clock_t startTime = clock();

    // determine the change in memory usage due to invoking model.initialiState
    auto command = [&model, state]() mutable { state = model.initializeState(); };
    const size_t leak = estimateMemoryChangeForCommand(command, MAX_N_TRIES);

    long double leak_percent = 100.0 * double(leak) / model_size;

    long double dT = (long double)(clock() - startTime) / CLOCKS_PER_SEC;
    long double meanT = 1.0e3 * dT / MAX_N_TRIES; // in ms

    cout << "Approximate leak size: " << leak / 1024.0 << "KB or " <<
        leak_percent << "% of model size." << endl;
    cout << "Average initialization time: " << meanT << "ms" << endl;

    // If we are leaking more than 0.5% of the model's footprint that is significant
    ASSERT((leak_percent) < 0.5, __FILE__, __LINE__,
        "testMemoryUsage: state initialization leak > 0.5% of model memory footprint.");
}
<commit_msg>Remove custom nSamples for memory use estimate<commit_after>/* -------------------------------------------------------------------------- *
 *                        OpenSim:  testInitState.cpp                         *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Author(s): Peter Eastman, Ajay Seth                                        *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */
#include <stdint.h>
#include <OpenSim/Simulation/Manager/Manager.h>
#include <OpenSim/Simulation/Control/ControlSetController.h>
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/LoadOpenSimLibrary.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

using namespace OpenSim;
using namespace std;

//==============================================================================
// testInitState tests that a Model consistently generates the same default
// state from its initSystem() method. It also tests that when the properties
// are updated (after a simulation) that the defaults match the values in the
// new state.
//==============================================================================
void testStates(const string& modelFile);
//==============================================================================
// testMemoryUsage tests that repeated initialization of the state does not
// cause the memory footprint of the process to increase significantly.
//==============================================================================
void testMemoryUsage(const string& modelFile);

static const int MAX_N_TRIES = 100;

int main()
{
    try {
        LoadOpenSimLibrary("osimActuators");
        testStates("arm26.osim");
        testMemoryUsage("arm26.osim");
        testMemoryUsage("PushUpToesOnGroundWithMuscles.osim");
    }
    catch (const Exception& e) {
        cout << "testInitState failed: ";
        e.print(cout);
        return 1;
    }
    catch (const std::exception& e) {
        cout << "testInitState failed: " << e.what() << endl;
        return 1;
    }
    cout << "Done" << endl;
    return 0;
}

//==============================================================================
// Test Cases
//==============================================================================
void testStates(const string& modelFile)
{
    using namespace SimTK;

    //==========================================================================
    // Setup OpenSim model
    Model model(modelFile);
    ControlSetController* controller = new ControlSetController();
    controller->setControlSetFileName("arm26_StaticOptimization_controls.xml");

    model.addController( controller );
    // original default state
    State& state = model.initSystem();

    // hold on to original default continuous state variables
    Vector y1 = state.getY();
    y1 = state.getY();
    //y1.dump("y1: Initial state:");

    // update state to contain muscle states that yield muscle equilibrium
    model.equilibrateMuscles(state);
    state.getY().dump("y1: State after equilibrateMuscles:");
    //==========================================================================
    // Compute the force and torque at the specified times.

    RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
    Manager manager(model, integrator);
    manager.setInitialTime(0.0);
    manager.setFinalTime(0.05);

    // update state after a short simulation forward in time
    manager.integrate(state);

    // continuous state variables after simulation
    Vector y2 = state.getY();
    //y2.dump("y2: State after integration:");

    // reset model working state to default state
    State& state2 = model.initializeState();

    // another version of default continuous state variables
    // should be unaffected by simulation of the system
    Vector y3 = state2.getY();
    //y3.dump("y3: Model reset to Initial state:");

    // update state to contain muscle states that yield muscle equilibrium
    model.equilibrateMuscles(state2);
    state.getY().dump("y3: State after equilibrateMuscles:");
    //==========================================================================
    // Compute the force and torque at the specified times.

    RungeKuttaMersonIntegrator integrator2(model.getMultibodySystem());
    Manager manager2(model, integrator);
    manager2.setInitialTime(0.0);
    manager2.setFinalTime(0.05);

    // update state after a short simulation forward in time
    manager2.integrate(state2);

    // get the default continuous state variables updated
    // from the state after the simulation
    Vector y4 = state2.getY();

    //y4.dump("y4: Default State after second simulation:");

    for (int i = 0; i < y1.size(); i++)
    {
        cout << i <<" : y1[i] = " << y1[i] << " :: y3[i] = " << y3[i] << endl;
        ASSERT_EQUAL(y1[i], y3[i], 1e-5,__FILE__, __LINE__,
            "Model failed to maintain default state after simulation.");
        cout << i <<" : y2[i] = " << y2[i] << " :: y4[i] = " << y4[i] << endl;
        ASSERT_EQUAL(y2[i], y4[i], 1e-5,__FILE__, __LINE__,
            "Model failed to properly update default state after simulation.");
    }
    ASSERT(max(abs(y1-y2)) > 1e-4);
}

void testMemoryUsage(const string& modelFile)
{
    using namespace SimTK;

    // Throw an exception if we cannot validate estimates
    // of memory with current instrumentation
    validateMemoryUseEstimates();

    //=========================================================================
    // Estimate the size of the model when loaded into memory
    auto creator = [modelFile]() {
        Model* model = new Model(modelFile);
        model->finalizeFromProperties();
        return model;
    };

    size_t model_size =
        estimateMemoryChangeForCreator<Model>(creator, 5);

    OPENSIM_THROW_IF(model_size == 0, OpenSim::Exception,
        "Model size was estimated to be zero.");

    Model model(modelFile);
    State& state = model.initSystem();

    // also time how long initializing the state takes
    clock_t startTime = clock();

    // determine the change in memory usage due to invoking model.initialiState
    auto command = [&model, state]() mutable { state = model.initializeState(); };
    const size_t leak = estimateMemoryChangeForCommand(command, MAX_N_TRIES);

    long double leak_percent = 100.0 * double(leak) / model_size;

    long double dT = (long double)(clock() - startTime) / CLOCKS_PER_SEC;
    long double meanT = 1.0e3 * dT / MAX_N_TRIES; // in ms

    cout << "Approximate leak size: " << leak / 1024.0 << "KB or " <<
        leak_percent << "% of model size." << endl;
    cout << "Average initialization time: " << meanT << "ms" << endl;

    // If we are leaking more than 0.5% of the model's footprint that is significant
    ASSERT((leak_percent) < 0.5, __FILE__, __LINE__,
        "testMemoryUsage: state initialization leak > 0.5% of model memory footprint.");
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAMRUtilities.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 <iostream>
#include <cassert>
#include <mpi.h>

#include "vtkAMRUtilities.h"
#include "vtkAMRBox.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkMultiProcessController.h"
#include "vtkMPIController.h"
#include "vtkUniformGrid.h"
#include "vtkImageToStructuredGrid.h"

//-----------------------------------------------------------------------------
//           H E L P E R   M E T H O D S  &   M A C R O S
//-----------------------------------------------------------------------------
#define CHECK_TEST( P, testName, rval ) {                                 \
  if( !P ) {                                                              \
    std::cerr << "ERROR:" << testName << " FAILED!\n";                    \
    std::cerr << "Location:" << __FILE__ << ":" << __LINE__ << std::endl; \
    ++rval;                                                               \
  }                                                                       \
}

// Description:
// Gets the grid for the given process
void WriteUniformGrid( vtkUniformGrid *myGrid, std::string prefix )
{
  assert( "Input Grid is not NULL" && (myGrid != NULL) );

  vtkImageToStructuredGrid* myImage2StructuredGridFilter =
      vtkImageToStructuredGrid::New();
  assert( "Image-2-StructuredGridFilter" &&
          (myImage2StructuredGridFilter != NULL) );

  myImage2StructuredGridFilter->SetInput( myGrid );
  myImage2StructuredGridFilter->Update();
  vtkStructuredGrid* myStructuredGrid =
      myImage2StructuredGridFilter->GetOutput();

}

// Description:
// Gets the grid for the given process
void GetGrid( vtkUniformGrid *myGrid, int &level, int &index,
              vtkMultiProcessController *myController )
{
  assert( "Input Grid is not NULL" && (myGrid != NULL) );
  assert( "Null Multi-process controller encountered" &&
          (myController != NULL) );

  switch( myController->GetLocalProcessId() )
    {
      case 0:
        {
          level=index=0;
          double myOrigin[3] = {0.0,0.0,0.0};
          int ndim[3] = {4,4,0};
          double spacing[3] = {1,1,1};
          myGrid->Initialize();
          myGrid->SetOrigin( myOrigin );
          myGrid->SetSpacing( spacing );
          myGrid->SetDimensions( ndim );
        }
        break;
      case 1:
        {
          level=1;index=0;
          double myOrigin[3] = {1.0,1.0,0.0};
          int ndim[3] = {7,4,0};
          double spacing[3] = {1/3,1/3,1/3};
          myGrid->Initialize();
          myGrid->SetOrigin( myOrigin );
          myGrid->SetSpacing( spacing );
          myGrid->SetDimensions( ndim );
        }
        break;
      default:
        std::cerr << "Undefined process!\n";
        std::cerr.flush();
        myGrid->Delete();
        myGrid=NULL;
    }

}

// Description:
// Get the AMR data-structure for the given process
void GetAMRDataSet(
    vtkHierarchicalBoxDataSet *amrData,
    vtkMultiProcessController *myController )
{
  assert( "Input AMR Data is NULL!" && (amrData != NULL) );
  assert( "Null Multi-process controller encountered" &&
           (myController != NULL) );

  int level = -1;
  int index = -1;
  vtkUniformGrid* myGrid = vtkUniformGrid::New();
  GetGrid( myGrid, level, index, myController );
  assert( "Invalid level" && (level >= 0) );
  assert( "Invalid index" && (index >= 0) );

  amrData->SetDataSet( level, index, myGrid );
  myGrid->Delete();
}

//-----------------------------------------------------------------------------
//                   T E S T   M E T H O D S
//-----------------------------------------------------------------------------

// Description:
// Tests the functionality for computing the global data-set origin.
bool TestComputeDataSetOrigin( vtkMultiProcessController *myController )
{
  assert( "Null Multi-process controller encountered" &&
          (myController != NULL) );
  myController->Barrier();

  vtkHierarchicalBoxDataSet* myAMRData = vtkHierarchicalBoxDataSet::New();
  GetAMRDataSet( myAMRData, myController );
  double origin[3];
  vtkAMRUtilities::ComputeDataSetOrigin( origin, myAMRData, myController );
  myAMRData->Delete();

  myController->Barrier();
  std::cout << myController->GetLocalProcessId() << ": ";
  std::cout << origin[0] << ", " << origin[1] << ", " << origin[2] << std::endl;
  std::cout.flush();
  myController->Barrier();

  if( (origin[0] == 0.0) && (origin[1] == 0.0) && (origin[2] == 0.0) )
    return true;
  else
    return false;
}

// Description:
// Main Test driver
int TestAMRUtilities(int,char*[])
{
  vtkMultiProcessController *myController =
      vtkMultiProcessController::GetGlobalController();
  assert( "Null Multi-process controller encountered" &&
            (myController != NULL) );

  // Synchronize Processes
  myController->Barrier();

  int rval=0;
  CHECK_TEST( TestComputeDataSetOrigin(myController),"ComputeOrigin", rval );

  // Synchronize Processes
  myController->Barrier();
  return( rval );
}

//-----------------------------------------------------------------------------
//                   P R O G R A M    M A I N
//-----------------------------------------------------------------------------

int main( int argc, char **argv )
{
  MPI_Init(&argc,&argv);

  vtkMPIController* contr = vtkMPIController::New();
  contr->Initialize( &argc, &argv, 1);

  vtkMultiProcessController::SetGlobalController(contr);

  int rc = TestAMRUtilities( argc, argv );
  contr->Barrier();

  contr->Finalize();
  contr->Delete();
  return rc;
}
<commit_msg>BUGFIX: Fix 2-D vtkUniformGrid Construction<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestAMRUtilities.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 <iostream>
#include <sstream>
#include <cassert>
#include <mpi.h>

#include "vtkAMRUtilities.h"
#include "vtkAMRBox.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkMultiProcessController.h"
#include "vtkMPIController.h"
#include "vtkUniformGrid.h"
#include "vtkImageToStructuredGrid.h"
#include "vtkStructuredGridWriter.h"

//-----------------------------------------------------------------------------
//           H E L P E R   M E T H O D S  &   M A C R O S
//-----------------------------------------------------------------------------
#define CHECK_TEST( P, testName, rval ) {                                 \
  if( !P ) {                                                              \
    std::cerr << "ERROR:" << testName << " FAILED!\n";                    \
    std::cerr << "Location:" << __FILE__ << ":" << __LINE__ << std::endl; \
    ++rval;                                                               \
  }                                                                       \
}

// Description:
// Gets the grid for the given process
void WriteUniformGrid( vtkUniformGrid *myGrid, std::string prefix )
{
  assert( "Input Grid is not NULL" && (myGrid != NULL) );

  vtkImageToStructuredGrid* myImage2StructuredGridFilter =
      vtkImageToStructuredGrid::New();
  assert( "Cannot create Image2StructuredGridFilter" &&
          (myImage2StructuredGridFilter != NULL) );

  myImage2StructuredGridFilter->SetInput( myGrid );
  myImage2StructuredGridFilter->Update();
  vtkStructuredGrid* myStructuredGrid =
      myImage2StructuredGridFilter->GetOutput();
  assert( "Structured Grid output is NULL!" &&
          (myStructuredGrid != NULL) );

  vtkStructuredGridWriter *myWriter = vtkStructuredGridWriter::New();
  myWriter->SetFileName( prefix.c_str() );
  myWriter->SetInput( myStructuredGrid );
  myWriter->Update();
  myWriter->Delete();
  myImage2StructuredGridFilter->Delete();
}

// Description:
// Gets the grid for the given process
void GetGrid( vtkUniformGrid *myGrid, int &level, int &index,
              vtkMultiProcessController *myController )
{
  assert( "Input Grid is not NULL" && (myGrid != NULL) );
  assert( "Null Multi-process controller encountered" &&
          (myController != NULL) );

  switch( myController->GetLocalProcessId() )
    {
      case 0:
        {
          level=index=0;
          double myOrigin[3] = {0.0,0.0,0.0};
          int ndim[3] = {4,4,1};
          double spacing[3] = {1,1,1};
          myGrid->Initialize();
          myGrid->SetOrigin( myOrigin );
          myGrid->SetSpacing( spacing );
          myGrid->SetDimensions( ndim );
        }
        break;
      case 1:
        {
          level=1;index=0;
          double myOrigin[3] = {1.0,1.0,0.0};
          int ndim[3] = {5,3,1};
          double spacing[3] = {0.5,0.5,0.5};
          myGrid->Initialize();
          myGrid->SetOrigin( myOrigin );
          myGrid->SetSpacing( spacing );
          myGrid->SetDimensions( ndim );
        }
        break;
      default:
        std::cerr << "Undefined process!\n";
        std::cerr.flush();
        myGrid->Delete();
        myGrid=NULL;
    }

}

// Description:
// Get the AMR data-structure for the given process
void GetAMRDataSet(
    vtkHierarchicalBoxDataSet *amrData,
    vtkMultiProcessController *myController )
{
  assert( "Input AMR Data is NULL!" && (amrData != NULL) );
  assert( "Null Multi-process controller encountered" &&
           (myController != NULL) );

  int level = -1;
  int index = -1;
  vtkUniformGrid* myGrid = vtkUniformGrid::New();
  GetGrid( myGrid, level, index, myController );
  assert( "Invalid level" && (level >= 0) );
  assert( "Invalid index" && (index >= 0) );
  std::ostringstream oss;
  oss.clear();
  oss.str("");
  oss << "Process_" << myController->GetLocalProcessId() << "_GRID_";
  oss << "L" << level << "_" << index << ".vtk";
  WriteUniformGrid( myGrid, oss.str( ) );

  amrData->SetDataSet( level, index, myGrid );
  myGrid->Delete();
}

//-----------------------------------------------------------------------------
//                   T E S T   M E T H O D S
//-----------------------------------------------------------------------------

// Description:
// Tests the functionality for computing the global data-set origin.
bool TestComputeDataSetOrigin( vtkMultiProcessController *myController )
{
  assert( "Null Multi-process controller encountered" &&
          (myController != NULL) );
  myController->Barrier();

  vtkHierarchicalBoxDataSet* myAMRData = vtkHierarchicalBoxDataSet::New();
  GetAMRDataSet( myAMRData, myController );
  double origin[3];
  vtkAMRUtilities::ComputeDataSetOrigin( origin, myAMRData, myController );
  myAMRData->Delete();

  myController->Barrier();
  std::cout << myController->GetLocalProcessId() << ": ";
  std::cout << origin[0] << ", " << origin[1] << ", " << origin[2] << std::endl;
  std::cout.flush();
  myController->Barrier();

  if( (origin[0] == 0.0) && (origin[1] == 0.0) && (origin[2] == 0.0) )
    return true;
  else
    return false;
}

// Description:
// Main Test driver
int TestAMRUtilities(int,char*[])
{
  vtkMultiProcessController *myController =
      vtkMultiProcessController::GetGlobalController();
  assert( "Null Multi-process controller encountered" &&
            (myController != NULL) );

  // Synchronize Processes
  myController->Barrier();

  int rval=0;
  CHECK_TEST( TestComputeDataSetOrigin(myController),"ComputeOrigin", rval );

  // Synchronize Processes
  myController->Barrier();
  return( rval );
}

//-----------------------------------------------------------------------------
//                   P R O G R A M    M A I N
//-----------------------------------------------------------------------------

int main( int argc, char **argv )
{
  MPI_Init(&argc,&argv);

  vtkMPIController* contr = vtkMPIController::New();
  contr->Initialize( &argc, &argv, 1);

  vtkMultiProcessController::SetGlobalController(contr);

  int rc = TestAMRUtilities( argc, argv );
  contr->Barrier();

  contr->Finalize();
  contr->Delete();
  return rc;
}
<|endoftext|>


<commit_before>/* FasTC
 * Copyright (c) 2014 University of North Carolina at Chapel Hill.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes, without
 * fee, and without a written agreement is hereby granted, provided that the
 * above copyright notice, this paragraph, and the following four paragraphs
 * appear in all copies.
 *
 * Permission to incorporate this software into commercial products may be
 * obtained by contacting the authors or the Office of Technology Development
 * at the University of North Carolina at Chapel Hill <otd@unc.edu>.
 *
 * This software program and documentation are copyrighted by the University of
 * North Carolina at Chapel Hill. The software program and documentation are
 * supplied "as is," without any accompanying services from the University of
 * North Carolina at Chapel Hill or the authors. The University of North
 * Carolina at Chapel Hill and the authors do not warrant that the operation of
 * the program will be uninterrupted or error-free. The end-user understands
 * that the program was developed for research purposes and is advised not to
 * rely exclusively on the program for any reason.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
 * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
 * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
 * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
 * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
 * AN "AS IS" BASIS, AND THE UNIVERSITY  OF NORTH CAROLINA AT CHAPEL HILL AND
 * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Please send all BUG REPORTS to <pavel@cs.unc.edu>.
 *
 * The authors may be contacted via:
 *
 * Pavel Krajcevski
 * Dept of Computer Science
 * 201 S Columbia St
 * Frederick P. Brooks, Jr. Computer Science Bldg
 * Chapel Hill, NC 27599-3175
 * USA
 *
 * <http://gamma.cs.unc.edu/FasTC/>
 */

#include "gtest/gtest.h"
#include "MatrixBase.h"

static const float kEpsilon = 1e-6;

TEST(MatrixBase, Constructors) {
  FasTC::MatrixBase<float, 3, 4> m3f;
  FasTC::MatrixBase<double, 1, 1> m1d;
  FasTC::MatrixBase<int, 7, 200> m7i;
  FasTC::MatrixBase<unsigned, 16, 16> m16u;

#define TEST_VECTOR_COPY_CONS(mat, t, n, m)     \
  do {                                          \
    FasTC::MatrixBase<t, n, m> d##mat (mat);    \
    for(int i = 0; i < n*m; i++) {              \
      EXPECT_EQ(d##mat [i], mat[i]);            \
    }                                           \
  } while(0)                                    \

  TEST_VECTOR_COPY_CONS(m3f, float, 3, 4);
  TEST_VECTOR_COPY_CONS(m1d, double, 1, 1);
  TEST_VECTOR_COPY_CONS(m7i, int, 7, 200);
  TEST_VECTOR_COPY_CONS(m16u, unsigned, 16, 16);

#undef TEST_VECTOR_COPY_CONS
}

TEST(MatrixBase, Accessors) {
  FasTC::MatrixBase<float, 3, 1> v3f;
  v3f[0] = 1.0f;
  v3f[1] = -2.3f;
  v3f[2] = 1000;

  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f[i], v3f(i));
  }

  v3f(0) = -1.0f;
  v3f(1) = 2.3f;
  v3f(2) = -1000;

  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f(i), v3f[i]);
  }
}

TEST(MatrixBase, PointerConversion) {
  FasTC::MatrixBase<float, 2, 3> v3f;
  v3f(0,0) = 1.0f;
  v3f(0,1) = -2.3f;
  v3f(0,2) = 1000.0f;
  v3f(1,0) = 1.0f;
  v3f(1,1) = -2.3f;
  v3f(1,2) = 1000.0f;

  float cmp[6] = { 1.0f, -2.3f, 1000.0f, 1.0f, -2.3f, 1000.0f };
  const float *v3fp = v3f;
  int result = memcmp(cmp, v3fp, 6 * sizeof(float));
  EXPECT_EQ(result, 0);

  cmp[0] = -1.0f;
  cmp[1] = 2.3f;
  cmp[2] = 1000.0f;
  cmp[3] = -1.0f;
  cmp[4] = 2.3f;
  cmp[5] = 1000.0f;
  v3f = cmp;
  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f[i], cmp[i]);
  }
}

TEST(MatrixBase, CastVector) {
  FasTC::MatrixBase<float, 3, 2> v3f;
  FasTC::MatrixBase<double, 3, 2> v3d = v3f;
  FasTC::MatrixBase<int, 3, 2> v3i = v3f;
  for(int i = 0; i < 3*2; i++) {
    EXPECT_EQ(v3d(i), static_cast<double>(v3f(i)));
    EXPECT_EQ(v3i(i), static_cast<int>(v3f(i)));
  }
}

TEST(MatrixBase, MatrixMultiplication) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(MatrixBase, VectorMultiplication) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(MatrixSquare, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(MatrixSquare, EigenvalueCalculation) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix2x2, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix3x3, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix4x4, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

<commit_msg>Add matrix multiplication test<commit_after>/* FasTC
 * Copyright (c) 2014 University of North Carolina at Chapel Hill.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes, without
 * fee, and without a written agreement is hereby granted, provided that the
 * above copyright notice, this paragraph, and the following four paragraphs
 * appear in all copies.
 *
 * Permission to incorporate this software into commercial products may be
 * obtained by contacting the authors or the Office of Technology Development
 * at the University of North Carolina at Chapel Hill <otd@unc.edu>.
 *
 * This software program and documentation are copyrighted by the University of
 * North Carolina at Chapel Hill. The software program and documentation are
 * supplied "as is," without any accompanying services from the University of
 * North Carolina at Chapel Hill or the authors. The University of North
 * Carolina at Chapel Hill and the authors do not warrant that the operation of
 * the program will be uninterrupted or error-free. The end-user understands
 * that the program was developed for research purposes and is advised not to
 * rely exclusively on the program for any reason.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
 * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
 * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
 * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
 * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
 * AN "AS IS" BASIS, AND THE UNIVERSITY  OF NORTH CAROLINA AT CHAPEL HILL AND
 * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Please send all BUG REPORTS to <pavel@cs.unc.edu>.
 *
 * The authors may be contacted via:
 *
 * Pavel Krajcevski
 * Dept of Computer Science
 * 201 S Columbia St
 * Frederick P. Brooks, Jr. Computer Science Bldg
 * Chapel Hill, NC 27599-3175
 * USA
 *
 * <http://gamma.cs.unc.edu/FasTC/>
 */

#include "gtest/gtest.h"
#include "MatrixBase.h"

static const float kEpsilon = 1e-6;

TEST(MatrixBase, Constructors) {
  FasTC::MatrixBase<float, 3, 4> m3f;
  FasTC::MatrixBase<double, 1, 1> m1d;
  FasTC::MatrixBase<int, 7, 200> m7i;
  FasTC::MatrixBase<unsigned, 16, 16> m16u;

#define TEST_VECTOR_COPY_CONS(mat, t, n, m)     \
  do {                                          \
    FasTC::MatrixBase<t, n, m> d##mat (mat);    \
    for(int i = 0; i < n*m; i++) {              \
      EXPECT_EQ(d##mat [i], mat[i]);            \
    }                                           \
  } while(0)                                    \

  TEST_VECTOR_COPY_CONS(m3f, float, 3, 4);
  TEST_VECTOR_COPY_CONS(m1d, double, 1, 1);
  TEST_VECTOR_COPY_CONS(m7i, int, 7, 200);
  TEST_VECTOR_COPY_CONS(m16u, unsigned, 16, 16);

#undef TEST_VECTOR_COPY_CONS
}

TEST(MatrixBase, Accessors) {
  FasTC::MatrixBase<float, 3, 1> v3f;
  v3f[0] = 1.0f;
  v3f[1] = -2.3f;
  v3f[2] = 1000;

  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f[i], v3f(i));
  }

  v3f(0) = -1.0f;
  v3f(1) = 2.3f;
  v3f(2) = -1000;

  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f(i), v3f[i]);
  }
}

TEST(MatrixBase, PointerConversion) {
  FasTC::MatrixBase<float, 2, 3> v3f;
  v3f(0,0) = 1.0f;
  v3f(0,1) = -2.3f;
  v3f(0,2) = 1000.0f;
  v3f(1,0) = 1.0f;
  v3f(1,1) = -2.3f;
  v3f(1,2) = 1000.0f;

  float cmp[6] = { 1.0f, -2.3f, 1000.0f, 1.0f, -2.3f, 1000.0f };
  const float *v3fp = v3f;
  int result = memcmp(cmp, v3fp, 6 * sizeof(float));
  EXPECT_EQ(result, 0);

  cmp[0] = -1.0f;
  cmp[1] = 2.3f;
  cmp[2] = 1000.0f;
  cmp[3] = -1.0f;
  cmp[4] = 2.3f;
  cmp[5] = 1000.0f;
  v3f = cmp;
  for(int i = 0; i < 3; i++) {
    EXPECT_EQ(v3f[i], cmp[i]);
  }
}

TEST(MatrixBase, CastVector) {
  FasTC::MatrixBase<float, 3, 2> v3f;
  FasTC::MatrixBase<double, 3, 2> v3d = v3f;
  FasTC::MatrixBase<int, 3, 2> v3i = v3f;
  for(int i = 0; i < 3*2; i++) {
    EXPECT_EQ(v3d(i), static_cast<double>(v3f(i)));
    EXPECT_EQ(v3i(i), static_cast<int>(v3f(i)));
  }
}

TEST(MatrixBase, MatrixMultiplication) {
  FasTC::MatrixBase<int, 2, 3> a;
  a(0, 0) = 1; a(0, 1) = 2; a(0, 2) = 3;
  a(1, 0) = 4; a(1, 1) = 5; a(1, 2) = 6;

  FasTC::MatrixBase<int, 3, 5> b;
  b(0, 0) = -1;  b(0, 1) =  2;  b(0, 2) = -4; b(0, 3) =  5; b(0, 4) = 0;
  b(1, 0) =  1;  b(1, 1) =  2;  b(1, 2) =  4; b(1, 3) =  6; b(1, 4) = 3;
  b(2, 0) = -1;  b(2, 1) = -2;  b(2, 2) = -3; b(2, 3) = -4; b(2, 4) = 5;

  FasTC::MatrixBase<float, 2, 5> amb = a * b;
  EXPECT_NEAR(amb(0, 0), -2, kEpsilon);
  EXPECT_NEAR(amb(0, 1), 0, kEpsilon);
  EXPECT_NEAR(amb(0, 2), -5, kEpsilon);
  EXPECT_NEAR(amb(0, 3), 5, kEpsilon);
  EXPECT_NEAR(amb(0, 4), 21, kEpsilon);

  EXPECT_NEAR(amb(1, 0), -5, kEpsilon);
  EXPECT_NEAR(amb(1, 1), 6, kEpsilon);
  EXPECT_NEAR(amb(1, 2), -14, kEpsilon);
  EXPECT_NEAR(amb(1, 3), 26, kEpsilon);
  EXPECT_NEAR(amb(1, 4), 45, kEpsilon);
}

TEST(MatrixBase, VectorMultiplication) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(MatrixSquare, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(MatrixSquare, EigenvalueCalculation) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix2x2, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix3x3, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

TEST(Matrix4x4, Constructors) {
  // Stub
  EXPECT_EQ(0, 1);
}

<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@berlin-consortium.org>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#include "Berlin/RegionImpl.hh"
#include "Berlin/TransformImpl.hh"
#include "Berlin/Math.hh"
#include <iomanip>
#include <cassert>

using namespace Warsaw;
using namespace Math;

RegionImpl::RegionImpl()
  : valid(false), xalign(0.), yalign(0.), zalign(0.), _this_valid(false)
{
  lower.x = lower.y = 0.;
  upper.x = upper.y = 0.;
  lower.z = upper.z = 0.;
}

RegionImpl::RegionImpl(const RegionImpl &region)
  : valid(region.valid),
    lower(region.lower),
    upper(region.upper),
    xalign(region.xalign),
    yalign(region.yalign),
    zalign(region.zalign),
    _this_valid(false)
{}

RegionImpl::RegionImpl(Region_ptr region)
  : _this_valid(false)
{
  RegionImpl::copy(region);
}

RegionImpl::RegionImpl(Region_ptr region, Transform_ptr transformation)
  : _this_valid(false)
{
  RegionImpl::copy(region);
  if (!CORBA::is_nil(transformation) && !transformation->identity())
    RegionImpl::apply_transform(transformation);
}

RegionImpl::RegionImpl(Region_ptr region, TransformImpl *transformation)
  : _this_valid(false)
{
  RegionImpl::copy(region);
  if (!transformation->identity())
    RegionImpl::apply_transform(transformation->matrix());
}

RegionImpl::~RegionImpl() {}

RegionImpl &RegionImpl::operator = (const RegionImpl &region)
{
  assert(_active);
  valid = region.valid;
  lower = region.lower;
  upper = region.upper;
  xalign = region.xalign;
  yalign = region.yalign;
  zalign = region.zalign;
  return *this;
}

CORBA::Boolean RegionImpl::defined() { return valid;}
void RegionImpl::clear() { valid = false;}

CORBA::Boolean RegionImpl::contains(const Vertex &v)
{
  return (valid &&
	  v.x >= lower.x && v.x <= upper.x &&
	  v.y >= lower.y && v.y <= upper.y &&
	  v.z >= lower.z && v.z <= upper.z
	  );
}

CORBA::Boolean RegionImpl::contains_plane(const Vertex &v, Axis a)
{
  bool b = false;
  if (valid)
    {
      switch (a)
	{
	case xaxis:
	  b = (v.y >= lower.y && v.y <= upper.y &&
	       v.z >= lower.z && v.z <= upper.z);
	  break;
	case yaxis:
	  b = (v.x >= lower.x && v.x <= upper.x &&
	       v.z >= lower.z && v.z <= upper.z);
	  break;
	case zaxis:
	  b = (v.x >= lower.x && v.x <= upper.x &&
	       v.y >= lower.y && v.y <= upper.y);
	  break;
	}
    }
  return b;
}

CORBA::Boolean RegionImpl::intersects(Region_ptr region)
{
  if (valid)
    {
      Vertex l, u;
      region->bounds(l, u);
      return lower.x <= u.x && upper.x >= l.x && lower.y <= u.y && upper.y >= l.y;
    }
  return false;
}

CORBA::Boolean RegionImpl::intersects(const RegionImpl &region) const
{
  if (valid && region.valid)
    return (lower.x <= region.upper.x &&
	    upper.x >= region.lower.x &&
	    lower.y <= region.upper.y &&
	    upper.y >= region.lower.y);
  else return false;
}

void RegionImpl::copy(Region_ptr region)
{
  if (!CORBA::is_nil(region) && region->defined())
    {
      Warsaw::Region::Allotment x, y, z;
      region->span(xaxis, x);
      region->span(yaxis, y);
      region->span(zaxis, z);
      valid = true;
      lower.x = x.begin;
      lower.y = y.begin;
      lower.z = z.begin;
      upper.x = x.end;
      upper.y = y.end;
      upper.z = z.end;
      xalign = x.align;
      yalign = y.align;
      zalign = z.align;
    }
}

void RegionImpl::merge_intersect(Region_ptr region)
{
  if (region->defined())
    {
      if (valid)
	{
	  Vertex l, u;
	  region->bounds(l, u);
	  merge_max(lower, l);
	  merge_min(upper, u);
        }
      else copy(region);
    }
}

void RegionImpl::merge_union(Region_ptr region)
{
  if (region->defined())
    {
      if (valid)
	{
	  Vertex l, u;
	  region->bounds(l, u);
	  merge_min(lower, l);
	  merge_max(upper, u);
        }
      else copy(region);
    }
}

void RegionImpl::subtract(Region_ptr region)
{
  // not implemented
}

void RegionImpl::apply_transform(Transform_ptr transformation)
{
  if (!valid) return;
  Transform::Matrix matrix;
  transformation->store_matrix(matrix);
  apply_transform(matrix);
};

/*
 * note: the new region is the bounding box of the transformed
 *       old region
 *
 * This algorithm takes advantage of some
 * interesting properties of affine transformations: i.e., opposite sides
 * are always parallel and same in length.  Another property of
 * affine transformation is that the transformed center of a box
 * is equal to the center of the transformed box.  Realizing these
 * properties, finding the transformed box can be broken down as finding
 * the effective width, height, depth, and center.  The last is easy.
 * Each of the other three values is found by first breaking down
 * each of the transformed axis vectors into x, y,  and z vectors.
 * Joining all the absolute vectors on a certain axis gives you
 * the size of the box on that axis.  Width, for example,
 * forms a (w, 0, 0) vector.  After transformation, it becomes
 * (Xw, Yw, Zw). The new width is then given as abs(Xw) + abs(Xh) + abs(Xd)
 */
void RegionImpl::apply_transform(const Transform::Matrix &matrix)
{
  Vertex o;

  origin(o);
  o *= matrix;

  Coord lx = upper.x - lower.x;
  Coord ly = upper.y - lower.y;
  Coord lz = upper.z - lower.z;

  Vertex center;
  center.x = (upper.x + lower.x) * 0.5;
  center.y = (upper.y + lower.y) * 0.5;
  center.z = (upper.z + lower.z) * 0.5;

  // transform the center
  center *= matrix;

  // optimized computation of new width and height
  Coord nlx = Math::abs(lx * matrix[0][0]) + Math::abs(ly * matrix[0][1]) + Math::abs(lz * matrix[0][2]);
  Coord nly = Math::abs(lx * matrix[1][0]) + Math::abs(ly * matrix[1][1]) + Math::abs(lz * matrix[1][2]);
  Coord nlz = Math::abs(lx * matrix[2][0]) + Math::abs(ly * matrix[2][1]) + Math::abs(lz * matrix[2][2]);

  // form the new box
  lower.x = center.x - nlx * 0.5;
  upper.x = center.x + nlx * 0.5;
  lower.y = center.y - nly * 0.5;
  upper.y = center.y + nly * 0.5;
  lower.z = center.z - nlz * 0.5;
  upper.z = center.z + nlz * 0.5;

  if (!Math::equal(nlx, 0., 1e-4)) xalign = (o.x - lower.x) / nlx;
  if (!Math::equal(nly, 0., 1e-4)) yalign = (o.y - lower.y) / nly;
  if (!Math::equal(nlz, 0., 1e-4)) zalign = (o.z - lower.z) / nlz;
}

void RegionImpl::bounds(Vertex &l, Vertex &u)
{
  l = lower;
  u = upper;
}

void RegionImpl::center(Vertex &c)
{
  c.x = (lower.x + upper.x) * 0.5;
  c.y = (lower.y + upper.y) * 0.5;
  c.z = 0.0;
}

void RegionImpl::origin(Vertex &v)
{
  v.x = span_origin(lower.x, upper.x, xalign);
  v.y = span_origin(lower.y, upper.y, yalign);
  v.z = span_origin(lower.z, upper.z, zalign);
}

void RegionImpl::span(Axis a, Warsaw::Region::Allotment &s)
{
  switch (a)
    {
    case xaxis:
      s.begin = lower.x;
      s.end = upper.x;
      s.align = xalign;
      break;
    case yaxis:
      s.begin = lower.y;
      s.end = upper.y;
      s.align = yalign;
      break;
    case zaxis:
      s.begin = lower.z;
      s.end = upper.z;
      s.align = zalign;
      break;
    }
}

void RegionImpl::outline(Path_out)
{
};

std::ostream &operator << (std::ostream &os, const RegionImpl &region)
{
  os << "X(" << region.lower.x << ',' << region.upper.x;
  if (!Math::equal(region.xalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.xalign;
  os << "), Y(" << region.lower.y << ',' << region.upper.y;
  if (!Math::equal(region.yalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.yalign;
  os << "), Z(" << region.lower.z << ',' << region.upper.z;
  if (!Math::equal(region.zalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.zalign;
  os << ')';
  return os;
}
<commit_msg>fixed little omission<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@berlin-consortium.org>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */
#include "Berlin/RegionImpl.hh"
#include "Berlin/TransformImpl.hh"
#include "Berlin/Math.hh"
#include <iomanip>
#include <cassert>

using namespace Warsaw;
using namespace Math;

RegionImpl::RegionImpl()
  : valid(false), xalign(0.), yalign(0.), zalign(0.), _this_valid(false)
{
  lower.x = lower.y = 0.;
  upper.x = upper.y = 0.;
  lower.z = upper.z = 0.;
}

RegionImpl::RegionImpl(const RegionImpl &region)
  : valid(region.valid),
    lower(region.lower),
    upper(region.upper),
    xalign(region.xalign),
    yalign(region.yalign),
    zalign(region.zalign),
    _this_valid(false)
{}

RegionImpl::RegionImpl(Region_ptr region)
  : _this_valid(false)
{
  RegionImpl::copy(region);
}

RegionImpl::RegionImpl(Region_ptr region, Transform_ptr transformation)
  : _this_valid(false)
{
  RegionImpl::copy(region);
  if (!CORBA::is_nil(transformation) && !transformation->identity())
    RegionImpl::apply_transform(transformation);
}

RegionImpl::RegionImpl(Region_ptr region, TransformImpl *transformation)
  : _this_valid(false)
{
  RegionImpl::copy(region);
  if (!transformation->identity())
    RegionImpl::apply_transform(transformation->matrix());
}

RegionImpl::~RegionImpl() {}

RegionImpl &RegionImpl::operator = (const RegionImpl &region)
{
  assert(_active);
  valid = region.valid;
  lower = region.lower;
  upper = region.upper;
  xalign = region.xalign;
  yalign = region.yalign;
  zalign = region.zalign;
  return *this;
}

CORBA::Boolean RegionImpl::defined() { return valid;}
void RegionImpl::clear() { valid = false;}

CORBA::Boolean RegionImpl::contains(const Vertex &v)
{
  return (valid &&
	  v.x >= lower.x && v.x <= upper.x &&
	  v.y >= lower.y && v.y <= upper.y &&
	  v.z >= lower.z && v.z <= upper.z
	  );
}

CORBA::Boolean RegionImpl::contains_plane(const Vertex &v, Axis a)
{
  bool b = false;
  if (valid)
    {
      switch (a)
	{
	case xaxis:
	  b = (v.y >= lower.y && v.y <= upper.y &&
	       v.z >= lower.z && v.z <= upper.z);
	  break;
	case yaxis:
	  b = (v.x >= lower.x && v.x <= upper.x &&
	       v.z >= lower.z && v.z <= upper.z);
	  break;
	case zaxis:
	  b = (v.x >= lower.x && v.x <= upper.x &&
	       v.y >= lower.y && v.y <= upper.y);
	  break;
	}
    }
  return b;
}

CORBA::Boolean RegionImpl::intersects(Region_ptr region)
{
  if (valid)
    {
      Vertex l, u;
      region->bounds(l, u);
      return lower.x <= u.x && upper.x >= l.x && lower.y <= u.y && upper.y >= l.y;
    }
  return false;
}

CORBA::Boolean RegionImpl::intersects(const RegionImpl &region) const
{
  if (valid && region.valid)
    return (lower.x <= region.upper.x &&
	    upper.x >= region.lower.x &&
	    lower.y <= region.upper.y &&
	    upper.y >= region.lower.y);
  else return false;
}

void RegionImpl::copy(Region_ptr region)
{
  if (!CORBA::is_nil(region) && region->defined())
    {
      Warsaw::Region::Allotment x, y, z;
      region->span(xaxis, x);
      region->span(yaxis, y);
      region->span(zaxis, z);
      valid = true;
      lower.x = x.begin;
      lower.y = y.begin;
      lower.z = z.begin;
      upper.x = x.end;
      upper.y = y.end;
      upper.z = z.end;
      xalign = x.align;
      yalign = y.align;
      zalign = z.align;
    }
}

void RegionImpl::merge_intersect(Region_ptr region)
{
  if (region->defined())
    {
      if (valid)
	{
	  Vertex l, u;
	  region->bounds(l, u);
	  merge_max(lower, l);
	  merge_min(upper, u);
        }
      else copy(region);
    }
}

void RegionImpl::merge_union(Region_ptr region)
{
  if (region->defined())
    {
      if (valid)
	{
	  Vertex l, u;
	  region->bounds(l, u);
	  merge_min(lower, l);
	  merge_max(upper, u);
        }
      else copy(region);
    }
}

void RegionImpl::subtract(Region_ptr region)
{
  // not implemented
}

void RegionImpl::apply_transform(Transform_ptr transformation)
{
  if (!valid) return;
  Transform::Matrix matrix;
  transformation->store_matrix(matrix);
  apply_transform(matrix);
};

/*
 * note: the new region is the bounding box of the transformed
 *       old region
 *
 * This algorithm takes advantage of some
 * interesting properties of affine transformations: i.e., opposite sides
 * are always parallel and same in length.  Another property of
 * affine transformation is that the transformed center of a box
 * is equal to the center of the transformed box.  Realizing these
 * properties, finding the transformed box can be broken down as finding
 * the effective width, height, depth, and center.  The last is easy.
 * Each of the other three values is found by first breaking down
 * each of the transformed axis vectors into x, y,  and z vectors.
 * Joining all the absolute vectors on a certain axis gives you
 * the size of the box on that axis.  Width, for example,
 * forms a (w, 0, 0) vector.  After transformation, it becomes
 * (Xw, Yw, Zw). The new width is then given as abs(Xw) + abs(Xh) + abs(Xd)
 */
void RegionImpl::apply_transform(const Transform::Matrix &matrix)
{
  Vertex o;

  origin(o);
  o *= matrix;

  Coord lx = upper.x - lower.x;
  Coord ly = upper.y - lower.y;
  Coord lz = upper.z - lower.z;

  Vertex center;
  center.x = (upper.x + lower.x) * 0.5;
  center.y = (upper.y + lower.y) * 0.5;
  center.z = (upper.z + lower.z) * 0.5;

  // transform the center
  center *= matrix;

  // optimized computation of new width and height
  Coord nlx = Math::abs(lx * matrix[0][0]) + Math::abs(ly * matrix[0][1]) + Math::abs(lz * matrix[0][2]);
  Coord nly = Math::abs(lx * matrix[1][0]) + Math::abs(ly * matrix[1][1]) + Math::abs(lz * matrix[1][2]);
  Coord nlz = Math::abs(lx * matrix[2][0]) + Math::abs(ly * matrix[2][1]) + Math::abs(lz * matrix[2][2]);

  // form the new box
  lower.x = center.x - nlx * 0.5;
  upper.x = center.x + nlx * 0.5;
  lower.y = center.y - nly * 0.5;
  upper.y = center.y + nly * 0.5;
  lower.z = center.z - nlz * 0.5;
  upper.z = center.z + nlz * 0.5;

  if (!Math::equal(nlx, 0., 1e-4)) xalign = (o.x - lower.x) / nlx;
  if (!Math::equal(nly, 0., 1e-4)) yalign = (o.y - lower.y) / nly;
  if (!Math::equal(nlz, 0., 1e-4)) zalign = (o.z - lower.z) / nlz;
}

void RegionImpl::bounds(Vertex &l, Vertex &u)
{
  l = lower;
  u = upper;
}

void RegionImpl::center(Vertex &c)
{
  c.x = (lower.x + upper.x) * 0.5;
  c.y = (lower.y + upper.y) * 0.5;
  c.z = 0.0;
}

void RegionImpl::origin(Vertex &v)
{
  v.x = span_origin(lower.x, upper.x, xalign);
  v.y = span_origin(lower.y, upper.y, yalign);
  v.z = span_origin(lower.z, upper.z, zalign);
}

void RegionImpl::span(Axis a, Warsaw::Region::Allotment &s)
{
  switch (a)
    {
    case xaxis:
      s.begin = lower.x;
      s.end = upper.x;
      s.align = xalign;
      break;
    case yaxis:
      s.begin = lower.y;
      s.end = upper.y;
      s.align = yalign;
      break;
    case zaxis:
      s.begin = lower.z;
      s.end = upper.z;
      s.align = zalign;
      break;
    }
}

void RegionImpl::outline(Path_out)
{
};

std::ostream &operator << (std::ostream &os, const RegionImpl &region)
{
  if (!region.valid) os << "undef";
  else
    {
      os << "X(" << region.lower.x << ',' << region.upper.x;
      if (!Math::equal(region.xalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.xalign;
      os << "), Y(" << region.lower.y << ',' << region.upper.y;
      if (!Math::equal(region.yalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.yalign;
      os << "), Z(" << region.lower.z << ',' << region.upper.z;
      if (!Math::equal(region.zalign, 0., 1e-2)) os << " @ " << std::setprecision(1) << region.zalign;
      os << ')';
    }
      return os;
}
<|endoftext|>


<commit_before>// Time:  O(|V| + |E|)
// Space: O(|V|)

class Solution {
public:
    struct node {
        int parent;
        vector<int>neighbors;
    };
    bool validTree(int n, vector<pair<int, int>>& edges) {
        if (edges.size() != n - 1) {
            return false;
        }

        unordered_map<int,node> nodes;
        unordered_set<int> visited;
        for (const auto& edge : edges) {
            nodes[edge.first].neighbors.emplace_back(edge.second);
            nodes[edge.second].neighbors.emplace_back(edge.first);
        }
        for (int i = 0; i < n; ++i) {
            nodes[i].parent = -1;
        }

        queue<int> q;
        q.emplace(0);
        visited.insert(0);
        while (!q.empty()) {
            int i = q.front();
            q.pop();
            for (const auto& n : nodes[i].neighbors) {
                if (n != nodes[i].parent) {
                    if (visited.find(n) != visited.end()) {
                        return false;
                    } else {
                        visited.insert(n);
                        nodes[n].parent = i;
                        q.emplace(n);
                    }
                }
            }
        }
        return true;
    }
};
<commit_msg>Update graph-valid-tree.cpp<commit_after>// Time:  O(|V| + |E|)
// Space: O(|V|)

class Solution {
public:
    struct node {
        int parent;
        vector<int>neighbors;
    };
    bool validTree(int n, vector<pair<int, int>>& edges) {
        if (edges.size() != n - 1) {
            return false;
        }

        unordered_map<int,node> nodes;
        for (const auto& edge : edges) {
            nodes[edge.first].neighbors.emplace_back(edge.second);
            nodes[edge.second].neighbors.emplace_back(edge.first);
        }
        for (int i = 0; i < n; ++i) {
            nodes[i].parent = -1;
        }

        unordered_set<int> visited;
        queue<int> q;
        q.emplace(0);
        while (!q.empty()) {
            int i = q.front();
            q.pop();
            visited.insert(i);
            for (const auto& n : nodes[i].neighbors) {
                if (n != nodes[i].parent) {
                    if (visited.find(n) != visited.end()) {
                        return false;
                    } else {
                        visited.insert(n);
                        nodes[n].parent = i;
                        q.emplace(n);
                    }
                }
            }
        }
        return true;
    }
};
<|endoftext|>