text: /*=========================================================================
   *
   *  Copyright Insight Software Consortium
   *
   *  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.txt
   *
   *  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 "itkMetaSceneConverter.h"
  
  /** \class MetaDummy
   *  dummy MetaObject to add to MetaScene
   */
  class MetaDummy : public MetaObject
  {
  public:
    MetaDummy(unsigned int dims = 3) : m_Value(0.0)
      {
        strcpy(m_ObjectTypeName,"Dummy");
        m_NDims = dims;
      }
    float GetValue() const { return m_Value; }
    void SetValue(float val) { m_Value = val; }
  
  protected:
    virtual void M_SetupReadFields(void) ITK_OVERRIDE
      {
        MetaObject::M_SetupReadFields();
        MET_FieldRecordType *mf = new MET_FieldRecordType;
        MET_InitReadField(mf,"Value", MET_FLOAT, true);
        mf->terminateRead = false;
        m_Fields.push_back(mf);
      }
    virtual void M_SetupWriteFields(void) ITK_OVERRIDE
      {
        strcpy(m_ObjectTypeName,"Dummy");
        MetaObject::M_SetupWriteFields();
  
        MET_FieldRecordType *mf = new MET_FieldRecordType;
        MET_InitWriteField(mf, "Value", MET_FLOAT, m_Value);
        m_Fields.push_back(mf);
      }
    virtual bool M_Read(void) ITK_OVERRIDE
      {
        if(!MetaObject::M_Read())
          {
          return false;
          }
        MET_FieldRecordType *mf_Value =
          MET_GetFieldRecord("Value",&m_Fields);
        if(mf_Value->defined)
          {
          m_Value = (float)mf_Value->value[0];
          }
        return true;
      }
  
  private:
    float m_Value;
  };
  
  namespace itk
  {
  /** \class DummySpatialObject
   */
  template <unsigned int TDimension = 3>
  class DummySpatialObject :
    public SpatialObject<TDimension>
  {
  public:
    typedef DummySpatialObject        Self;
    typedef SpatialObject<TDimension> Superclass;
    typedef SmartPointer<Self>        Pointer;
    typedef SmartPointer<const Self>  ConstPointer;
  
    /** method for creation through the object factory */
    itkNewMacro(Self);
  
    itkTypeMacro(DummySpatialObject, SpatialObject);
    void SetValue(float val)
      {
        this->m_Value = val;
      }
    float GetValue() const
      {
        return this->m_Value;
      }
  
  protected:
    DummySpatialObject() : m_Value(0.0)
      {
        this->SetDimension(TDimension);
        this->SetTypeName ("DummySpatialObject");
        this->GetProperty()->SetRed(1);
        this->GetProperty()->SetGreen(0);
        this->GetProperty()->SetBlue(0);
        this->GetProperty()->SetAlpha(1);
      }
    ~DummySpatialObject() {}
  
  private:
    DummySpatialObject(const Self &) ITK_DELETE_FUNCTION;
    void operator=(const Self &) ITK_DELETE_FUNCTION;
    float m_Value;
  };
  
  /** \class MetaConverterBase
   *  Dummy converter class
   */
  template< unsigned int NDimensions = 3 >
  class MetaDummyConverter :
      public MetaConverterBase< NDimensions >
  {
  public:
    /** Standard class typedefs */
    typedef MetaDummyConverter               Self;
    typedef MetaConverterBase< NDimensions > Superclass;
    typedef SmartPointer< Self >             Pointer;
    typedef SmartPointer< const Self >       ConstPointer;
  
    /** Method for creation through the object factory. */
    itkNewMacro(Self);
  
    /** Run-time type information (and related methods). */
    itkTypeMacro(MetaDummyConverter, MetaConverterBase);
  
    typedef typename Superclass::SpatialObjectType SpatialObjectType;
    typedef typename SpatialObjectType::Pointer    SpatialObjectPointer;
    typedef typename Superclass::MetaObjectType    MetaObjectType;
  
    /** Specific class types for conversion */
    typedef DummySpatialObject<NDimensions>               DummySpatialObjectType;
    typedef typename DummySpatialObjectType::Pointer      DummySpatialObjectPointer;
    typedef typename DummySpatialObjectType::ConstPointer DummySpatialObjectConstPointer;
    typedef MetaDummy                                     DummyMetaObjectType;
  
    /** Convert the MetaObject to Spatial Object */
    virtual SpatialObjectPointer MetaObjectToSpatialObject(const MetaObjectType *mo) ITK_OVERRIDE
    {
      const DummyMetaObjectType *dummyMO = dynamic_cast<const MetaDummy *>(mo);
      if(dummyMO == ITK_NULLPTR)
        {
        itkExceptionMacro(<< "Can't convert MetaObject to MetaDummy");
        }
      DummySpatialObjectPointer dummySO = DummySpatialObjectType::New();
      dummySO->SetValue(dummyMO->GetValue());
  
      dummySO->GetProperty()->SetName( dummyMO->Name() );
      dummySO->SetId( dummyMO->ID() );
      dummySO->SetParentId( dummyMO->ParentID() );
      dummySO->GetProperty()->SetRed(dummyMO->Color()[0]);
      dummySO->GetProperty()->SetGreen(dummyMO->Color()[1]);
      dummySO->GetProperty()->SetBlue(dummyMO->Color()[2]);
      dummySO->GetProperty()->SetAlpha(dummyMO->Color()[3]);
  
      return dummySO.GetPointer();
    }
  
    /** Convert the SpatialObject to MetaObject */
    virtual MetaObjectType *SpatialObjectToMetaObject(const SpatialObjectType *spatialObject) ITK_OVERRIDE
    {
      DummySpatialObjectConstPointer dummySO =
        dynamic_cast<const DummySpatialObjectType *>(spatialObject);
      if(dummySO.IsNull())
        {
        itkExceptionMacro(<< "Can't downcast SpatialObject to DummySpatialObject");
        }
      DummyMetaObjectType *dummyMO = new MetaDummy;
      dummyMO->SetValue(dummySO->GetValue());
  
      dummyMO->ID( dummySO->GetId() );
      dummyMO->Color( dummySO->GetProperty()->GetRed(),
                      dummySO->GetProperty()->GetGreen(),
                      dummySO->GetProperty()->GetBlue(),
                      dummySO->GetProperty()->GetAlpha() );
  
      return dummyMO;
    }
  
  protected:
    /** Create the specific MetaObject for this class */
    virtual MetaObjectType *CreateMetaObject() ITK_OVERRIDE
    {
      return dynamic_cast<MetaObjectType *>(new DummyMetaObjectType);
    }
  
    MetaDummyConverter() {}
    ~MetaDummyConverter() {}
  
  private:
    MetaDummyConverter(const Self &) ITK_DELETE_FUNCTION;
    void operator=(const Self &) ITK_DELETE_FUNCTION;
  
  };
  
  }
  
  int itkNewMetaObjectTypeTest(int, char* [])
  {
    const float Pi(3.1415926);
  
    typedef itk::SceneSpatialObject<3>                 SceneType;
    typedef itk::DummySpatialObject<3>                 DummyType;
    typedef itk::MetaSceneConverter<3,unsigned short>  MetaSceneConverterType;
  
    typedef itk::MetaDummyConverter<3>                 DummyConverterType;
  
    SceneType::Pointer scene(SceneType::New());
  
    DummyType::Pointer dummy(DummyType::New());
    dummy->GetProperty()->SetName("Dummy");
    dummy->SetId(1);
    dummy->SetValue(Pi);
  
    scene->AddSpatialObject(dummy);
  
    DummyConverterType::Pointer dummyConverter(DummyConverterType::New());
  
    MetaSceneConverterType converter;
    converter.RegisterMetaConverter("Dummy","DummySpatialObject",dummyConverter);
  
    MetaScene *metaScene = converter.CreateMetaScene(scene);
    SceneType::Pointer myScene = converter.CreateSpatialObjectScene(metaScene);
  
    if(!myScene)
      {
      std::cout << "No Scene : [FAILED]" << std::endl;
      delete metaScene;
      return EXIT_FAILURE;
      }
    if(myScene->GetNumberOfObjects(1) != 1)
      {
      std::cout << "found " << myScene->GetNumberOfObjects(1) << " instead of 1 [FAILED]"
                << std::endl;
      delete metaScene;
      return EXIT_FAILURE;
      }
    SceneType::ObjectListType *mySceneChildren =
      myScene->GetObjects();
    SceneType::ObjectListType::const_iterator obj;
  
    for(obj = mySceneChildren->begin(); obj != mySceneChildren->end(); ++obj)
      {
      std::string childType((*obj)->GetTypeName());
      if(childType != "DummySpatialObject")
        {
        std::cout << "Expected child type Dummy but found "
                  << childType << " [FAILED]" << std::endl;
        delete metaScene;
        delete mySceneChildren;
        return EXIT_FAILURE;
        }
      DummyType::Pointer p = dynamic_cast<DummyType *>((*obj).GetPointer());
      if(p.IsNull())
        {
        std::cout << "Unable to downcast child SpatialObject to DummySpatialObject"
                  << "[FAILED]" << std::endl;
        delete metaScene;
        delete mySceneChildren;
        return EXIT_FAILURE;
        }
      float value = p->GetValue();
      if(std::fabs(value - Pi) > 0.00001)
        {
        std::cout << "Expected value " << Pi
                  << "but found " << value << std::endl;
        delete metaScene;
        delete mySceneChildren;
        return EXIT_FAILURE;
        }
      }
    delete mySceneChildren;
    delete metaScene;
    return EXIT_SUCCESS;
  }
  