<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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.
 */

#ifndef otbFunctorImageFilter_hxx
#define otbFunctorImageFilter_hxx

#include "otbFunctorImageFilter.h"
#include "itkProgressReporter.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageScanlineIterator.h"

namespace otb
{
namespace functor_filter_details
{
// Variadic SetRequestedRegion

// This function sets the requested region for one image
template<class T> int SetInputRequestedRegion(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius, bool pad)
{
  assert(img&&"Input image is a nullptr");

  auto currentRegion = region;

  // Hopefully this will be optimized out by compiler
  if(pad)
    currentRegion.PadByRadius(radius);

  // The ugly cast in all ITK filters
  T * nonConstImg = const_cast<T*>(img);

  if(currentRegion.Crop(img->GetLargestPossibleRegion()))
    {
    nonConstImg->SetRequestedRegion(currentRegion);
    return 0;
    }
  else
    {
    nonConstImg->SetRequestedRegion(currentRegion);

    // build an exception
    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
    e.SetLocation("::SetInputRequestedRegion<>()");
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(nonConstImg);
    throw e;
    }
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename HasNeighborhood, class Tuple, size_t...Is> auto SetInputRequestedRegionsImpl(Tuple & t, const itk::ImageRegion<2> & region, std::index_sequence<Is...>,const itk::Size<2> & radius)
{
  return std::make_tuple(SetInputRequestedRegion(std::get<Is>(t),region,radius,typename std::tuple_element<Is,HasNeighborhood>::type::value_type())...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename HasNeighborhood,typename... T> auto SetInputRequestedRegions(std::tuple<T...> && t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius)
{
  return SetInputRequestedRegionsImpl<HasNeighborhood>(t,region,std::make_index_sequence<sizeof...(T)>{},radius);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Tuple, size_t...Is> auto GetNumberOfComponentsPerInputImpl(Tuple & t, std::index_sequence<Is...>)
{
  return std::array<size_t,sizeof...(Is)>{{std::get<Is>(t)->GetNumberOfComponentsPerPixel()...}};
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename ...T> auto GetNumberOfComponentsPerInput(std::tuple<T...> & t)
{
  return GetNumberOfComponentsPerInputImpl(t, std::make_index_sequence<sizeof...(T)>{});
}

template <typename N> struct MakeIterator {};

template <> struct MakeIterator<std::false_type>
{
  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>&)
  {
    itk::ImageRegionConstIterator<T> it(img,region);
    return it;
  }
};

template <> struct MakeIterator<std::true_type>
{
  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
  {
    itk::ConstNeighborhoodIterator<T> it(radius,img,region);
    return it;
  }
};

// Will be easier to write in c++17 with std::apply and fold expressions
template <class TNeigh, class Tuple, size_t...Is> auto MakeIteratorsImpl(const Tuple& t, const itk::ImageRegion<2> & region, const itk::Size<2> & radius, std::index_sequence<Is...>, TNeigh)
{
  return std::make_tuple(MakeIterator<typename std::tuple_element<Is,TNeigh>::type >::Make(std::get<Is>(t),region,radius)...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template<class TNeigh, typename... T> auto MakeIterators(std::tuple<T...> &&t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius, TNeigh n)
  {
    return MakeIteratorsImpl(t,region,radius,std::make_index_sequence<sizeof...(T)>{},n);
  }

// Variadic call of operator from iterator tuple
template <typename T> struct GetProxy{};

template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
{
  static decltype(auto) Get(const itk::ImageRegionConstIterator<T> & t)
{
  return t.Get();
}
};

template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
{
  static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t)
{
  return t.GetNeighborhood();
}
};

template <class Oper> struct OperProxy : public OperProxy<decltype(&std::remove_reference<Oper>::type::operator())> {};

template<class Out, class ... In> struct OperProxy<Out(*)(In...)>
{
  template <class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...) const>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class Out, class ... In> struct OperProxy<void(*)(Out&, In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...) const>
{
  template template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Tuple, class Out, class Oper, size_t...Is> auto CallOperatorImpl(Tuple& t, Out & out, Oper & oper,std::index_sequence<Is...>)
{
  OperProxy<Oper>::Compute(oper,out,GetProxy<typename std::remove_reference<decltype(std::get<Is>(t))>::type>::Get(std::get<Is>(t))...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Out, class Oper, typename ... Args> auto CallOperator(Out & out, Oper& oper, std::tuple<Args...> & t)
{
  CallOperatorImpl(t,out,oper,std::make_index_sequence<sizeof...(Args)>{});
}

// Variadic move of iterators
// Will be easier to write in c++17 with std::apply and fold expressions
template<class Tuple,size_t...Is> auto MoveIteratorsImpl(Tuple & t, std::index_sequence<Is...>)
{
  return std::make_tuple(++(std::get<Is>(t) )...);
}

template<typename ... Args> void MoveIterators(std::tuple<Args...> & t)
{
  MoveIteratorsImpl(t,std::make_index_sequence<sizeof...(Args)>{});
}

// Default implementation does nothing
template <class F, class O, size_t N> struct NumberOfOutputComponents
{};

template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Image<T>,N>
  {
  // We can not be here if output type is VectorImage
    static void Set(const F&, otb::Image<T> *, std::array<size_t,N>){}
};

// O is a VectorImage AND F has a fixed OuptutSize static constexrp size_t;
template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::VectorImage<T>,N>
{
  static void Set(const F & f, otb::VectorImage<T> * outputImage, std::array<size_t,N> inNbBands)
  {
    outputImage->SetNumberOfComponentsPerPixel(f.OutputSize(inNbBands));
  }
};

} // end namespace functor_filter_details

template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>
::GenerateInputRequestedRegion()
{
  // Get requested region for output
  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
  auto requestedRegion = outputPtr->GetRequestedRegion();

  // Propagate to each variadic inputs, including possible radius
  // TODO: For now all inputs are padded with the radius, even if they
  // are not neighborhood based
  functor_filter_details::SetInputRequestedRegions<InputHasNeighborhood>(this->GetVariadicInputs(),requestedRegion, m_Radius);
}

template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>::GenerateOutputInformation()
{
  // Call Superclass implementation
  Superclass::GenerateOutputInformation();

  // Get All variadic inputs
  auto inputs = this->GetVariadicInputs();

  // Retrieve an array of number of components per input
  auto inputNbComps = functor_filter_details::GetNumberOfComponentsPerInput(inputs);

  // Call the helper to set the number of components for the output image
  functor_filter_details::NumberOfOutputComponents<TFunction,OutputImageType,inputNbComps.size()>::Set(m_Functor,this->GetOutput(),inputNbComps);
}

/**
 * ThreadedGenerateData Performs the neighborhood-wise operation
 */
template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
{
  // Build output iterator
  itk::ImageScanlineIterator<OutputImageType> outIt(this->GetOutput(),outputRegionForThread);
  itk::ProgressReporter p(this,threadId,outputRegionForThread.GetNumberOfPixels());

  // This will build a tuple of iterators to be used
  auto inputIterators = functor_filter_details::MakeIterators(this->GetVariadicInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{});

  // Build a default value
  typename OutputImageType::PixelType outputValueHolder;
  itk::NumericTraits<typename OutputImageType::PixelType>::SetLength(outputValueHolder,this->GetOutput()->GetNumberOfComponentsPerPixel());

  while(!outIt.IsAtEnd())
    {
    // MoveIterartors will ++ all iterators in the tuple
    for(;!outIt.IsAtEndOfLine();++outIt,functor_filter_details::MoveIterators(inputIterators))
      {
      // This will call the operator with inputIterators Get() results
      // and fill outputValueHolder with the result.
      functor_filter_details::CallOperator(outputValueHolder,m_Functor,inputIterators);
      outIt.Set(outputValueHolder);
      // Update progress
      p.CompletedPixel();
      }
    outIt.NextLine();
    }
}

} // end namespace otb

#endif
<commit_msg>COMP: Fix compilation error (double template keyword)<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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.
 */

#ifndef otbFunctorImageFilter_hxx
#define otbFunctorImageFilter_hxx

#include "otbFunctorImageFilter.h"
#include "itkProgressReporter.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageScanlineIterator.h"

namespace otb
{
namespace functor_filter_details
{
// Variadic SetRequestedRegion

// This function sets the requested region for one image
template<class T> int SetInputRequestedRegion(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius, bool pad)
{
  assert(img&&"Input image is a nullptr");

  auto currentRegion = region;

  // Hopefully this will be optimized out by compiler
  if(pad)
    currentRegion.PadByRadius(radius);

  // The ugly cast in all ITK filters
  T * nonConstImg = const_cast<T*>(img);

  if(currentRegion.Crop(img->GetLargestPossibleRegion()))
    {
    nonConstImg->SetRequestedRegion(currentRegion);
    return 0;
    }
  else
    {
    nonConstImg->SetRequestedRegion(currentRegion);

    // build an exception
    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
    e.SetLocation("::SetInputRequestedRegion<>()");
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(nonConstImg);
    throw e;
    }
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename HasNeighborhood, class Tuple, size_t...Is> auto SetInputRequestedRegionsImpl(Tuple & t, const itk::ImageRegion<2> & region, std::index_sequence<Is...>,const itk::Size<2> & radius)
{
  return std::make_tuple(SetInputRequestedRegion(std::get<Is>(t),region,radius,typename std::tuple_element<Is,HasNeighborhood>::type::value_type())...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename HasNeighborhood,typename... T> auto SetInputRequestedRegions(std::tuple<T...> && t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius)
{
  return SetInputRequestedRegionsImpl<HasNeighborhood>(t,region,std::make_index_sequence<sizeof...(T)>{},radius);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Tuple, size_t...Is> auto GetNumberOfComponentsPerInputImpl(Tuple & t, std::index_sequence<Is...>)
{
  return std::array<size_t,sizeof...(Is)>{{std::get<Is>(t)->GetNumberOfComponentsPerPixel()...}};
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <typename ...T> auto GetNumberOfComponentsPerInput(std::tuple<T...> & t)
{
  return GetNumberOfComponentsPerInputImpl(t, std::make_index_sequence<sizeof...(T)>{});
}

template <typename N> struct MakeIterator {};

template <> struct MakeIterator<std::false_type>
{
  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>&)
  {
    itk::ImageRegionConstIterator<T> it(img,region);
    return it;
  }
};

template <> struct MakeIterator<std::true_type>
{
  template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
  {
    itk::ConstNeighborhoodIterator<T> it(radius,img,region);
    return it;
  }
};

// Will be easier to write in c++17 with std::apply and fold expressions
template <class TNeigh, class Tuple, size_t...Is> auto MakeIteratorsImpl(const Tuple& t, const itk::ImageRegion<2> & region, const itk::Size<2> & radius, std::index_sequence<Is...>, TNeigh)
{
  return std::make_tuple(MakeIterator<typename std::tuple_element<Is,TNeigh>::type >::Make(std::get<Is>(t),region,radius)...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template<class TNeigh, typename... T> auto MakeIterators(std::tuple<T...> &&t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius, TNeigh n)
  {
    return MakeIteratorsImpl(t,region,radius,std::make_index_sequence<sizeof...(T)>{},n);
  }

// Variadic call of operator from iterator tuple
template <typename T> struct GetProxy{};

template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
{
  static decltype(auto) Get(const itk::ImageRegionConstIterator<T> & t)
{
  return t.Get();
}
};

template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
{
  static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t)
{
  return t.GetNeighborhood();
}
};

template <class Oper> struct OperProxy : public OperProxy<decltype(&std::remove_reference<Oper>::type::operator())> {};

template<class Out, class ... In> struct OperProxy<Out(*)(In...)>
{
  template <class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<Out(C::*)(In...) const>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    out = oper(in...);
  }
};

template<class Out, class ... In> struct OperProxy<void(*)(Out&, In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...)>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

template<class C, class Out, class ... In> struct OperProxy<void(C::*)(Out&, In...) const>
{
  template<class Oper> static void Compute(Oper& oper, Out& out, const In& ... in)
  {
    oper(out,in...);
  }
};

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Tuple, class Out, class Oper, size_t...Is> auto CallOperatorImpl(Tuple& t, Out & out, Oper & oper,std::index_sequence<Is...>)
{
  OperProxy<Oper>::Compute(oper,out,GetProxy<typename std::remove_reference<decltype(std::get<Is>(t))>::type>::Get(std::get<Is>(t))...);
}

// Will be easier to write in c++17 with std::apply and fold expressions
template <class Out, class Oper, typename ... Args> auto CallOperator(Out & out, Oper& oper, std::tuple<Args...> & t)
{
  CallOperatorImpl(t,out,oper,std::make_index_sequence<sizeof...(Args)>{});
}

// Variadic move of iterators
// Will be easier to write in c++17 with std::apply and fold expressions
template<class Tuple,size_t...Is> auto MoveIteratorsImpl(Tuple & t, std::index_sequence<Is...>)
{
  return std::make_tuple(++(std::get<Is>(t) )...);
}

template<typename ... Args> void MoveIterators(std::tuple<Args...> & t)
{
  MoveIteratorsImpl(t,std::make_index_sequence<sizeof...(Args)>{});
}

// Default implementation does nothing
template <class F, class O, size_t N> struct NumberOfOutputComponents
{};

template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Image<T>,N>
  {
  // We can not be here if output type is VectorImage
    static void Set(const F&, otb::Image<T> *, std::array<size_t,N>){}
};

// O is a VectorImage AND F has a fixed OuptutSize static constexrp size_t;
template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::VectorImage<T>,N>
{
  static void Set(const F & f, otb::VectorImage<T> * outputImage, std::array<size_t,N> inNbBands)
  {
    outputImage->SetNumberOfComponentsPerPixel(f.OutputSize(inNbBands));
  }
};

} // end namespace functor_filter_details

template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>
::GenerateInputRequestedRegion()
{
  // Get requested region for output
  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
  auto requestedRegion = outputPtr->GetRequestedRegion();

  // Propagate to each variadic inputs, including possible radius
  // TODO: For now all inputs are padded with the radius, even if they
  // are not neighborhood based
  functor_filter_details::SetInputRequestedRegions<InputHasNeighborhood>(this->GetVariadicInputs(),requestedRegion, m_Radius);
}

template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>::GenerateOutputInformation()
{
  // Call Superclass implementation
  Superclass::GenerateOutputInformation();

  // Get All variadic inputs
  auto inputs = this->GetVariadicInputs();

  // Retrieve an array of number of components per input
  auto inputNbComps = functor_filter_details::GetNumberOfComponentsPerInput(inputs);

  // Call the helper to set the number of components for the output image
  functor_filter_details::NumberOfOutputComponents<TFunction,OutputImageType,inputNbComps.size()>::Set(m_Functor,this->GetOutput(),inputNbComps);
}

/**
 * ThreadedGenerateData Performs the neighborhood-wise operation
 */
template <class TFunction, class TNameMap>
void
FunctorImageFilter<TFunction, TNameMap>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
{
  // Build output iterator
  itk::ImageScanlineIterator<OutputImageType> outIt(this->GetOutput(),outputRegionForThread);
  itk::ProgressReporter p(this,threadId,outputRegionForThread.GetNumberOfPixels());

  // This will build a tuple of iterators to be used
  auto inputIterators = functor_filter_details::MakeIterators(this->GetVariadicInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{});

  // Build a default value
  typename OutputImageType::PixelType outputValueHolder;
  itk::NumericTraits<typename OutputImageType::PixelType>::SetLength(outputValueHolder,this->GetOutput()->GetNumberOfComponentsPerPixel());

  while(!outIt.IsAtEnd())
    {
    // MoveIterartors will ++ all iterators in the tuple
    for(;!outIt.IsAtEndOfLine();++outIt,functor_filter_details::MoveIterators(inputIterators))
      {
      // This will call the operator with inputIterators Get() results
      // and fill outputValueHolder with the result.
      functor_filter_details::CallOperator(outputValueHolder,m_Functor,inputIterators);
      outIt.Set(outputValueHolder);
      // Update progress
      p.CompletedPixel();
      }
    outIt.NextLine();
    }
}

} // end namespace otb

#endif
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkDICOMQIIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkDICOMFileReaderSelector.h>

#include <mitkLogMacros.h>

#include <itkGDCMImageIO.h>

#include <itksys/SystemTools.hxx>

// dcmqi
#include <dcmqi/ImageSEGConverter.h>
#include <dcmqi/JSONSegmentationMetaInformationHandler.h>

namespace mitk
{
  std::vector<CustomMimeType *> MitkDICOMQIIOMimeTypes::Get()
  {
    std::vector<CustomMimeType *> mimeTypes;

    // order matters here (descending rank for mime types)

    mimeTypes.push_back(DICOMQI_MIMETYPE().Clone());

    return mimeTypes;
  }

  // Mime Types

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::MitkDICOMQIMimeType() : CustomMimeType(DICOMQI_MIMETYPE_NAME())
  {
    this->AddExtension("gdcm");
    this->AddExtension("dcm");
    this->AddExtension("DCM");
    this->AddExtension("dc3");
    this->AddExtension("DC3");
    this->AddExtension("ima");
    this->AddExtension("img");

    this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
    this->SetComment("DCMQI");
  }

  bool MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::AppliesTo(const std::string &path) const
  {
    bool canRead(CustomMimeType::AppliesTo(path));

    // fix for bug 18572
    // Currently this function is called for writing as well as reading, in that case
    // the image information can of course not be read
    // This is a bug, this function should only be called for reading.
    if (!itksys::SystemTools::FileExists(path.c_str()))
    {
      return canRead;
    }
    // end fix for bug 18572
    DcmFileFormat dcmFileFormat;
    OFCondition status = dcmFileFormat.loadFile(path.c_str());

    if (status.bad())
    {
      canRead = false;
    }

    if (!canRead)
    {
      return canRead;
    }

    OFString modality;
    if (dcmFileFormat.getDataset()->findAndGetOFString(DCM_Modality, modality).good())
    {
      if (modality.compare("SEG") == 0)
      {
        canRead = true;
      }
      else
      {
        canRead = false;
      }
    }

    return canRead;
  }

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType *MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::Clone() const
  {
    return new MitkDICOMQIMimeType(*this);
  }

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType MitkDICOMQIIOMimeTypes::DICOMQI_MIMETYPE()
  {
    return MitkDICOMQIMimeType();
  }

  // Names
  std::string MitkDICOMQIIOMimeTypes::DICOMQI_MIMETYPE_NAME()
  {
    // create a unique and sensible name for this mime type
    static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.seg";
    return name;
  }
}
<commit_msg>Remove not required extension from DICOM QI mime type. Change comment to DICOM SEG.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "mitkDICOMQIIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkDICOMFileReaderSelector.h>

#include <mitkLogMacros.h>

#include <itkGDCMImageIO.h>

#include <itksys/SystemTools.hxx>

// dcmqi
#include <dcmqi/ImageSEGConverter.h>
#include <dcmqi/JSONSegmentationMetaInformationHandler.h>

namespace mitk
{
  std::vector<CustomMimeType *> MitkDICOMQIIOMimeTypes::Get()
  {
    std::vector<CustomMimeType *> mimeTypes;

    // order matters here (descending rank for mime types)

    mimeTypes.push_back(DICOMQI_MIMETYPE().Clone());

    return mimeTypes;
  }

  // Mime Types

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::MitkDICOMQIMimeType() : CustomMimeType(DICOMQI_MIMETYPE_NAME())
  {
    this->AddExtension("dcm");
    this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
    this->SetComment("DICOM SEG");
  }

  bool MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::AppliesTo(const std::string &path) const
  {
    bool canRead(CustomMimeType::AppliesTo(path));

    // fix for bug 18572
    // Currently this function is called for writing as well as reading, in that case
    // the image information can of course not be read
    // This is a bug, this function should only be called for reading.
    if (!itksys::SystemTools::FileExists(path.c_str()))
    {
      return canRead;
    }
    // end fix for bug 18572
    DcmFileFormat dcmFileFormat;
    OFCondition status = dcmFileFormat.loadFile(path.c_str());

    if (status.bad())
    {
      canRead = false;
    }

    if (!canRead)
    {
      return canRead;
    }

    OFString modality;
    if (dcmFileFormat.getDataset()->findAndGetOFString(DCM_Modality, modality).good())
    {
      if (modality.compare("SEG") == 0)
      {
        canRead = true;
      }
      else
      {
        canRead = false;
      }
    }

    return canRead;
  }

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType *MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType::Clone() const
  {
    return new MitkDICOMQIMimeType(*this);
  }

  MitkDICOMQIIOMimeTypes::MitkDICOMQIMimeType MitkDICOMQIIOMimeTypes::DICOMQI_MIMETYPE()
  {
    return MitkDICOMQIMimeType();
  }

  // Names
  std::string MitkDICOMQIIOMimeTypes::DICOMQI_MIMETYPE_NAME()
  {
    // create a unique and sensible name for this mime type
    static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.seg";
    return name;
  }
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

//Poco headers
#include <Poco/Zip/Compress.h>
#include <Poco/Path.h>
#include <Poco/File.h>

#include "mitkNavigationToolStorageSerializer.h"
#include "mitkNavigationToolWriter.h"
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"
#include <mitkStandaloneDataStorage.h>
#include <mitkSceneIO.h>
#include <mitkIOUtil.h>

#include <sstream>

mitk::NavigationToolStorageSerializer::NavigationToolStorageSerializer()
{
  //create temp directory
  m_tempDirectory = mitk::IOUtil::CreateTemporaryDirectory();
  //Poco::File myFile(m_tempDirectory);
  //myFile.createDirectory();
}

mitk::NavigationToolStorageSerializer::~NavigationToolStorageSerializer()
{
 //remove temp directory
 Poco::File myFile(m_tempDirectory);
 try
  {
  if (myFile.exists()) myFile.remove(true);
  }
 catch(...)
  {
   MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!";
  }
}

bool mitk::NavigationToolStorageSerializer::Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage)
{
  //save every tool to temp directory
  mitk::NavigationToolWriter::Pointer myToolWriter = mitk::NavigationToolWriter::New();
  for(int i=0; i<storage->GetToolCount();i++)
  {
    std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
    if (!myToolWriter->DoWrite(fileName,storage->GetTool(i)))
      {
        mitkThrowException(mitk::IGTIOException) << "Could not write tool to tempory directory: " << filename;
      }
  }
  //add all files to zip archive
  std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out);
  if (!file.good()) //test if the zip archive is ready for writing
  {
    //first: clean up
    for (int i=0; i<storage->GetToolCount();i++)
    {
      std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
      std::remove(fileName.c_str());
    }
    //then: throw an exception
    mitkThrowException(mitk::IGTIOException) << "Could not open a file for writing: " << filename;
  }
  Poco::Zip::Compress zipper( file, true );
  for (int i=0; i<storage->GetToolCount();i++)
  {
    std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
    zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName));
    std::remove(fileName.c_str()); //delete file
  }
 zipper.close();
 file.close();

 return true;
 }

std::string mitk::NavigationToolStorageSerializer::convertIntToString(int i)
 {
  std::string s;
  std::stringstream out;
  out << i;
  s = out.str();
  return s;
 }
<commit_msg>renamed some variables<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

//Poco headers
#include <Poco/Zip/Compress.h>
#include <Poco/Path.h>
#include <Poco/File.h>

#include "mitkNavigationToolStorageSerializer.h"
#include "mitkNavigationToolWriter.h"
#include "mitkIGTException.h"
#include "mitkIGTIOException.h"
#include <mitkStandaloneDataStorage.h>
#include <mitkSceneIO.h>
#include <mitkIOUtil.h>

#include <sstream>

mitk::NavigationToolStorageSerializer::NavigationToolStorageSerializer()
{
  //create temp directory
  m_tempDirectory = mitk::IOUtil::CreateTemporaryDirectory();
  //Poco::File myFile(m_tempDirectory);
  //myFile.createDirectory();
}

mitk::NavigationToolStorageSerializer::~NavigationToolStorageSerializer()
{
 //remove temp directory
 Poco::File myFile(m_tempDirectory);
 try
  {
  if (myFile.exists()) myFile.remove(true);
  }
 catch(...)
  {
   MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!";
  }
}

bool mitk::NavigationToolStorageSerializer::Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage)
{
  //save every tool to temp directory
  mitk::NavigationToolWriter::Pointer myToolWriter = mitk::NavigationToolWriter::New();
  for(int i=0; i<storage->GetToolCount();i++)
  {
    std::string tempFileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
    if (!myToolWriter->DoWrite(tempFileName,storage->GetTool(i)))
      {
        mitkThrowException(mitk::IGTIOException) << "Could not write tool to tempory directory: " << tempFileName;
      }
  }
  //add all files to zip archive
  std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out);
  if (!file.good()) //test if the zip archive is ready for writing
  {
    //first: clean up
    for (int i=0; i<storage->GetToolCount();i++)
    {
      std::string tempFileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
      std::remove(tempFileName.c_str());
    }
    //then: throw an exception
    mitkThrowException(mitk::IGTIOException) << "Could not open a file for writing: " << filename;
  }
  Poco::Zip::Compress zipper( file, true );
  for (int i=0; i<storage->GetToolCount();i++)
  {
    std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool";
    zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName));
    std::remove(fileName.c_str()); //delete file
  }
 zipper.close();
 file.close();

 return true;
 }

std::string mitk::NavigationToolStorageSerializer::convertIntToString(int i)
 {
  std::string s;
  std::stringstream out;
  out << i;
  s = out.str();
  return s;
 }
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include <QmitkNumberPropertySlider.h>

#include <mitkPropertyObserver.h>
#include <mitkProperties.h>

#include <mitkRenderingManager.h>

#define DT_SHORT   1
#define DT_INT     2
#define DT_FLOAT   3
#define DT_DOUBLE  4

#define ROUND(x)       (((x) > 0) ?   int((x) + 0.5) :   int((x) - 0.5))
#define ROUND_SHORT(x) (((x) > 0) ? short((x) + 0.5) : short((x) - 0.5))

class QmitkNumberPropertySlider::Impl
{
public:

  Impl(QmitkNumberPropertySlider* q);

  void DisplayNumber();
  void adjustFactors(short, bool);

  class Editor : public mitk::PropertyEditor
  {
  public:
    Editor(mitk::IntProperty*, Impl* impl);
    Editor(mitk::FloatProperty*, Impl* impl);
    Editor(mitk::DoubleProperty*, Impl* impl);

    virtual void PropertyChanged();
    virtual void PropertyRemoved();

    void BeginModifyProperty()
    { mitk::PropertyEditor::BeginModifyProperty(); }
    void EndModifyProperty()
    { mitk::PropertyEditor::EndModifyProperty(); }

    union {
      mitk::GenericProperty<int>*     m_IntProperty;
      mitk::GenericProperty<float>*   m_FloatProperty;
      mitk::GenericProperty<double>*  m_DoubleProperty;
    };

    const int m_DataType;

  private:
    Impl* m_Impl;
  };

  std::auto_ptr<Editor> m_PropEditor;

  short m_DecimalPlaces;            // how many decimal places are shown
  double m_FactorPropertyToSlider; // internal conversion factor. neccessary because slider ranges work only with ints
  double m_FactorSliderToDisplay;  // internal conversion factor. neccessary because slider ranges work only with ints
  bool m_ShowPercents;              // whether values are given in percent (0.5 -> 50%)

  bool m_SelfChangeLock;

private:

  void initialize();

  QmitkNumberPropertySlider* q;
};

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::IntProperty* property, Impl* impl)
  : mitk::PropertyEditor(property)
  , m_IntProperty(property)
  , m_DataType(DT_INT)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::FloatProperty* property, Impl* impl)
  : mitk::PropertyEditor( property )
  , m_FloatProperty(property)
  , m_DataType(DT_FLOAT)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::DoubleProperty* property, Impl* impl)
  : mitk::PropertyEditor( property )
  , m_DoubleProperty(property)
  , m_DataType(DT_DOUBLE)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::~QmitkNumberPropertySlider()
{
}

void QmitkNumberPropertySlider::SetProperty(mitk::IntProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

void QmitkNumberPropertySlider::SetProperty(mitk::FloatProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

void QmitkNumberPropertySlider::SetProperty(mitk::DoubleProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

QmitkNumberPropertySlider::Impl::Impl(QmitkNumberPropertySlider* q)
  : m_DecimalPlaces(0)
  , m_FactorPropertyToSlider(1.0)
  , m_FactorSliderToDisplay(1.0)
  , m_ShowPercents(false)
  , m_SelfChangeLock(false)
  , q(q)
{
}

QmitkNumberPropertySlider::QmitkNumberPropertySlider(QWidget *parent)
  : QSlider(parent)
  , d(new Impl(this))
{
  connect( this, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)) );
  this->setEnabled(false);
}

void QmitkNumberPropertySlider::Impl::adjustFactors(short newDecimalPlaces, bool newShowPercents)
{
  int oldMax = q->maxValue();
  int oldMin = q->minValue();

  m_DecimalPlaces = newDecimalPlaces;
  m_ShowPercents = newShowPercents;

  m_FactorPropertyToSlider = pow(10.0,m_DecimalPlaces);
  m_FactorSliderToDisplay = 1.0 / m_FactorPropertyToSlider;

  if ( m_ShowPercents )
    m_FactorPropertyToSlider *= 100.0;

  q->setMinimum(oldMin);
  q->setMaximum(oldMax);
}

short QmitkNumberPropertySlider::getDecimalPlaces() const
{
  return d->m_DecimalPlaces;
}

void QmitkNumberPropertySlider::setDecimalPlaces(short places)
{
  if (d->m_PropEditor.get() == NULL) return;

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_FLOAT:
  case DT_DOUBLE:
  {
    d->adjustFactors( places, d->m_ShowPercents );
    d->DisplayNumber();
    break;
  }
  default:
    break;
  }
}

bool QmitkNumberPropertySlider::getShowPercent() const
{
  return d->m_ShowPercents;
}

void QmitkNumberPropertySlider::setShowPercent(bool showPercent)
{
  if ( showPercent == d->m_ShowPercents ) return; // nothing to change

  if (d->m_PropEditor.get() == NULL) return;

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_FLOAT:
  case DT_DOUBLE:
  {
    d->adjustFactors(d->m_DecimalPlaces, showPercent);
    break;
  }
  default:
  {
    break;
  }
  }

  d->DisplayNumber();
}

int QmitkNumberPropertySlider::minValue() const
{
  return ROUND( QSlider::minimum() / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setMinValue(int value)
{
  QSlider::setMinimum( ROUND(value * d->m_FactorPropertyToSlider ) );
}

int QmitkNumberPropertySlider::maxValue() const
{
  return ROUND( QSlider::maximum() / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setMaxValue(int value)
{
  QSlider::setMaximum( ROUND( value * d->m_FactorPropertyToSlider ) );
}

double QmitkNumberPropertySlider::doubleValue() const
{
  return static_cast<double>((QSlider::value()) / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setDoubleValue(double value)
{
  QSlider::setValue( ROUND( value * d->m_FactorPropertyToSlider ) );
}

void QmitkNumberPropertySlider::onValueChanged(int value)
{
  if (d->m_PropEditor.get() == NULL) return;

  if (d->m_SelfChangeLock) return; // valueChanged is even emitted, when this widget initiates a change to its value
                                // this may be useful some times, but in this use, it would be wrong:
                                //   (A) is an editor with 3 decimal places
                                //   (B) is an editor with 2 decimal places
                                //   User changes A's displayed value to 4.002
                                //   A's onValueChanged gets called, sets the associated Property to 4.002
                                //   B's onPropertyChanged gets called, sets its display to 4.00
                                //   B's onValueChanged gets called and sets the associated Property to 4.00
                                //   A's onPropertyChanged gets called, sets its display to 4.000

  d->m_PropEditor->BeginModifyProperty();

  double newValue( value / d->m_FactorPropertyToSlider );

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_INT:
  {
    d->m_PropEditor->m_IntProperty->SetValue(ROUND(newValue));
    break;
  }
  case DT_FLOAT:
  {
    d->m_PropEditor->m_FloatProperty->SetValue(newValue);
    break;
  }
  case DT_DOUBLE:
  {
    d->m_PropEditor->m_DoubleProperty->SetValue(newValue);
    break;
  }
  }
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();

  d->m_PropEditor->EndModifyProperty();
}

void QmitkNumberPropertySlider::Impl::Editor::PropertyChanged()
{
  m_Impl->DisplayNumber();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkNumberPropertySlider::Impl::Editor::PropertyRemoved()
{
  this->m_Property = NULL;
}

void QmitkNumberPropertySlider::Impl::DisplayNumber()
{
  if (m_PropEditor.get() == NULL) return;

  m_SelfChangeLock = true;
  switch (m_PropEditor->m_DataType)
  {
  case DT_INT:
  {
    int i = m_PropEditor->m_IntProperty->GetValue();
    q->setValue( i );
    break;
  }
  case DT_FLOAT:
  {
    float f = m_PropEditor->m_FloatProperty->GetValue();
    q->setDoubleValue( f );
    break;
  }
  case DT_DOUBLE:
  {
    double d = m_PropEditor->m_DoubleProperty->GetValue();
    q->setDoubleValue( d );
    break;
  }
  default:
    break;
  }
  m_SelfChangeLock = false;
}

<commit_msg>call PropertyRemoved for completeness<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include <QmitkNumberPropertySlider.h>

#include <mitkPropertyObserver.h>
#include <mitkProperties.h>

#include <mitkRenderingManager.h>

#define DT_SHORT   1
#define DT_INT     2
#define DT_FLOAT   3
#define DT_DOUBLE  4

#define ROUND(x)       (((x) > 0) ?   int((x) + 0.5) :   int((x) - 0.5))
#define ROUND_SHORT(x) (((x) > 0) ? short((x) + 0.5) : short((x) - 0.5))

class QmitkNumberPropertySlider::Impl
{
public:

  Impl(QmitkNumberPropertySlider* q);

  void DisplayNumber();
  void adjustFactors(short, bool);

  class Editor : public mitk::PropertyEditor
  {
  public:
    Editor(mitk::IntProperty*, Impl* impl);
    Editor(mitk::FloatProperty*, Impl* impl);
    Editor(mitk::DoubleProperty*, Impl* impl);

    virtual void PropertyChanged();
    virtual void PropertyRemoved();

    void BeginModifyProperty()
    { mitk::PropertyEditor::BeginModifyProperty(); }
    void EndModifyProperty()
    { mitk::PropertyEditor::EndModifyProperty(); }

    union {
      mitk::GenericProperty<int>*     m_IntProperty;
      mitk::GenericProperty<float>*   m_FloatProperty;
      mitk::GenericProperty<double>*  m_DoubleProperty;
    };

    const int m_DataType;

  private:
    Impl* m_Impl;
  };

  std::auto_ptr<Editor> m_PropEditor;

  short m_DecimalPlaces;            // how many decimal places are shown
  double m_FactorPropertyToSlider; // internal conversion factor. neccessary because slider ranges work only with ints
  double m_FactorSliderToDisplay;  // internal conversion factor. neccessary because slider ranges work only with ints
  bool m_ShowPercents;              // whether values are given in percent (0.5 -> 50%)

  bool m_SelfChangeLock;

private:

  void initialize();

  QmitkNumberPropertySlider* q;
};

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::IntProperty* property, Impl* impl)
  : mitk::PropertyEditor(property)
  , m_IntProperty(property)
  , m_DataType(DT_INT)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::FloatProperty* property, Impl* impl)
  : mitk::PropertyEditor( property )
  , m_FloatProperty(property)
  , m_DataType(DT_FLOAT)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::Impl::Editor::Editor(mitk::DoubleProperty* property, Impl* impl)
  : mitk::PropertyEditor( property )
  , m_DoubleProperty(property)
  , m_DataType(DT_DOUBLE)
  , m_Impl(impl)
{
}

QmitkNumberPropertySlider::~QmitkNumberPropertySlider()
{
}

void QmitkNumberPropertySlider::SetProperty(mitk::IntProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor->PropertyRemoved();
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

void QmitkNumberPropertySlider::SetProperty(mitk::FloatProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor->PropertyRemoved();
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

void QmitkNumberPropertySlider::SetProperty(mitk::DoubleProperty* property)
{
  if (property == NULL)
  {
    d->m_PropEditor->PropertyRemoved();
    d->m_PropEditor.reset();
    this->setEnabled(false);
  }
  else
  {
    d->m_PropEditor.reset(new Impl::Editor(property, d.get()));
    d->m_PropEditor->PropertyChanged();
    this->setEnabled(true);
  }
}

QmitkNumberPropertySlider::Impl::Impl(QmitkNumberPropertySlider* q)
  : m_DecimalPlaces(0)
  , m_FactorPropertyToSlider(1.0)
  , m_FactorSliderToDisplay(1.0)
  , m_ShowPercents(false)
  , m_SelfChangeLock(false)
  , q(q)
{
}

QmitkNumberPropertySlider::QmitkNumberPropertySlider(QWidget *parent)
  : QSlider(parent)
  , d(new Impl(this))
{
  connect( this, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)) );
  this->setEnabled(false);
}

void QmitkNumberPropertySlider::Impl::adjustFactors(short newDecimalPlaces, bool newShowPercents)
{
  int oldMax = q->maxValue();
  int oldMin = q->minValue();

  m_DecimalPlaces = newDecimalPlaces;
  m_ShowPercents = newShowPercents;

  m_FactorPropertyToSlider = pow(10.0,m_DecimalPlaces);
  m_FactorSliderToDisplay = 1.0 / m_FactorPropertyToSlider;

  if ( m_ShowPercents )
    m_FactorPropertyToSlider *= 100.0;

  q->setMinimum(oldMin);
  q->setMaximum(oldMax);
}

short QmitkNumberPropertySlider::getDecimalPlaces() const
{
  return d->m_DecimalPlaces;
}

void QmitkNumberPropertySlider::setDecimalPlaces(short places)
{
  if (d->m_PropEditor.get() == NULL) return;

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_FLOAT:
  case DT_DOUBLE:
  {
    d->adjustFactors( places, d->m_ShowPercents );
    d->DisplayNumber();
    break;
  }
  default:
    break;
  }
}

bool QmitkNumberPropertySlider::getShowPercent() const
{
  return d->m_ShowPercents;
}

void QmitkNumberPropertySlider::setShowPercent(bool showPercent)
{
  if ( showPercent == d->m_ShowPercents ) return; // nothing to change

  if (d->m_PropEditor.get() == NULL) return;

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_FLOAT:
  case DT_DOUBLE:
  {
    d->adjustFactors(d->m_DecimalPlaces, showPercent);
    break;
  }
  default:
  {
    break;
  }
  }

  d->DisplayNumber();
}

int QmitkNumberPropertySlider::minValue() const
{
  return ROUND( QSlider::minimum() / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setMinValue(int value)
{
  QSlider::setMinimum( ROUND(value * d->m_FactorPropertyToSlider ) );
}

int QmitkNumberPropertySlider::maxValue() const
{
  return ROUND( QSlider::maximum() / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setMaxValue(int value)
{
  QSlider::setMaximum( ROUND( value * d->m_FactorPropertyToSlider ) );
}

double QmitkNumberPropertySlider::doubleValue() const
{
  return static_cast<double>((QSlider::value()) / d->m_FactorPropertyToSlider );
}

void QmitkNumberPropertySlider::setDoubleValue(double value)
{
  QSlider::setValue( ROUND( value * d->m_FactorPropertyToSlider ) );
}

void QmitkNumberPropertySlider::onValueChanged(int value)
{
  if (d->m_PropEditor.get() == NULL) return;

  if (d->m_SelfChangeLock) return; // valueChanged is even emitted, when this widget initiates a change to its value
                                // this may be useful some times, but in this use, it would be wrong:
                                //   (A) is an editor with 3 decimal places
                                //   (B) is an editor with 2 decimal places
                                //   User changes A's displayed value to 4.002
                                //   A's onValueChanged gets called, sets the associated Property to 4.002
                                //   B's onPropertyChanged gets called, sets its display to 4.00
                                //   B's onValueChanged gets called and sets the associated Property to 4.00
                                //   A's onPropertyChanged gets called, sets its display to 4.000

  d->m_PropEditor->BeginModifyProperty();

  double newValue( value / d->m_FactorPropertyToSlider );

  switch (d->m_PropEditor->m_DataType)
  {
  case DT_INT:
  {
    d->m_PropEditor->m_IntProperty->SetValue(ROUND(newValue));
    break;
  }
  case DT_FLOAT:
  {
    d->m_PropEditor->m_FloatProperty->SetValue(newValue);
    break;
  }
  case DT_DOUBLE:
  {
    d->m_PropEditor->m_DoubleProperty->SetValue(newValue);
    break;
  }
  }
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();

  d->m_PropEditor->EndModifyProperty();
}

void QmitkNumberPropertySlider::Impl::Editor::PropertyChanged()
{
  m_Impl->DisplayNumber();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkNumberPropertySlider::Impl::Editor::PropertyRemoved()
{
  this->m_Property = NULL;
}

void QmitkNumberPropertySlider::Impl::DisplayNumber()
{
  if (m_PropEditor.get() == NULL) return;

  m_SelfChangeLock = true;
  switch (m_PropEditor->m_DataType)
  {
  case DT_INT:
  {
    int i = m_PropEditor->m_IntProperty->GetValue();
    q->setValue( i );
    break;
  }
  case DT_FLOAT:
  {
    float f = m_PropEditor->m_FloatProperty->GetValue();
    q->setDoubleValue( f );
    break;
  }
  case DT_DOUBLE:
  {
    double d = m_PropEditor->m_DoubleProperty->GetValue();
    q->setDoubleValue( d );
    break;
  }
  default:
    break;
  }
  m_SelfChangeLock = false;
}

<|endoftext|>


<commit_before>// SimbodySpeed.cpp
// Author: Frank C. Anderson
/*
 * Copyright (c) 2006, Stanford University. All rights reserved.
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//=============================================================================
// INCLUDES
//=============================================================================
#include "SimbodySpeed.h"
#include "SimbodyEngine.h"
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/SimmIO.h>
#include <OpenSim/Common/SimmMacros.h>

//=============================================================================
// STATICS
//=============================================================================
using namespace std;
using namespace SimTK;
using namespace OpenSim;

//=============================================================================
// CONSTRUCTOR(S) AND DESTRUCTOR
//=============================================================================
//_____________________________________________________________________________
/**
 * Default constructor.
 */
SimbodySpeed::SimbodySpeed() :
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
}

//_____________________________________________________________________________
/**
 * Destructor.
 */
SimbodySpeed::~SimbodySpeed()
{
}

//_____________________________________________________________________________
/**
 * Copy constructor.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
SimbodySpeed::SimbodySpeed(const SimbodySpeed &aSpeed) :
   AbstractSpeed(aSpeed),
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
	copyData(aSpeed);
}

//_____________________________________________________________________________
/**
 * Copy constructor from an AbstractSpeed.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
SimbodySpeed::SimbodySpeed(const AbstractSpeed &aSpeed) :
   AbstractSpeed(aSpeed),
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
	copyData(aSpeed);
}

//_____________________________________________________________________________
/**
 * Copy this speed and return a pointer to the copy.
 * The copy constructor for this class is used.
 *
 * @return Pointer to a copy of this SimbodySpeed.
 */
Object* SimbodySpeed::copy() const
{
	SimbodySpeed *gc = new SimbodySpeed(*this);
	return(gc);
}

//=============================================================================
// CONSTRUCTION METHODS
//=============================================================================
//_____________________________________________________________________________
/**
 * Copy data members from one SimbodySpeed to another.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
void SimbodySpeed::copyData(const SimbodySpeed &aSpeed)
{
	_defaultValue = aSpeed.getDefaultValue();
	_coordinateName = aSpeed._coordinateName;
	_engine = aSpeed._engine;
}

//_____________________________________________________________________________
/**
 * Copy data members from an AbstractSpeed to an SimbodySpeed.
 *
 * @param aSpeed AbstractSpeed to be copied.
 */
void SimbodySpeed::copyData(const AbstractSpeed &aSpeed)
{
	_defaultValue = aSpeed.getDefaultValue();
	_coordinate = aSpeed.getCoordinate();
	if (_coordinate)
		_coordinateName = _coordinate->getName();
	else
		_coordinateName = "Unassigned";
}

//_____________________________________________________________________________
/**
 * Set the data members of this SimbodySpeed to their null values.
 */
void SimbodySpeed::setNull(void)
{
	setType("SimbodySpeed");

	_coordinate = NULL;
	_engine = NULL;
	_mobilityIndex = -1;
	_engine = NULL;
}

//_____________________________________________________________________________
/**
 * Connect properties to local pointers.
 */
void SimbodySpeed::setupProperties(void)
{
	_defaultValueProp.setName("default_value");
	_defaultValueProp.setValue(0.0);
	_propertySet.append(&_defaultValueProp);

	_coordinateNameProp.setName("coordinate");
	_propertySet.append(&_coordinateNameProp);
}

//_____________________________________________________________________________
/**
 * Perform some set up functions that happen after the
 * object has been deserialized or copied.
 *
 * @param aEngine dynamics engine containing this SimbodySpeed.
 */
void SimbodySpeed::setup(AbstractDynamicsEngine* aEngine)
{
	// Base class;
	AbstractSpeed::setup(aEngine);

	_engine = dynamic_cast<SimbodyEngine*>(aEngine);

	_coordinate = _engine->getCoordinateSet()->get(_coordinateName);

	// If the user specified a default value, set the
	// current value to the default value.
	if (!_defaultValueProp.getUseDefault())
		setValue(_defaultValue);
}

//=============================================================================
// OPERATORS
//=============================================================================
//_____________________________________________________________________________
/**
 * Assignment operator.
 *
 * @return Reference to this object.
 */
SimbodySpeed& SimbodySpeed::operator=(const SimbodySpeed &aSpeed)
{
	// BASE CLASS
	AbstractSpeed::operator=(aSpeed);

	copyData(aSpeed);

	return(*this);
}

//=============================================================================
// COORDINATE
//=============================================================================
//_____________________________________________________________________________
/**
 * Set the coordinate that this speed corresponds to.
 *
 * @param Pointer to the coordinate.
 * @return Whether or not the coordinate was set.
 */
bool SimbodySpeed::setCoordinate(AbstractCoordinate *aCoordinate)
{
	_coordinate = aCoordinate;
	return true;
}
//_____________________________________________________________________________
/**
 * Set the name of the coordinate that this speed corresponds to. When creating
 * a new SimbodySpeed object, this method should be used rather than setCoordinate,
 * because setup() will use _coordinateName to set _coordinate (which needs
 * to be done when deserializing SimbodySpeed objects).
 *
 * @param Name of the coordinate.
 * @return Whether or not the coordinate was set.
 */
bool SimbodySpeed::setCoordinateName(const string& aCoordName)
{
	_coordinateName = aCoordName;
	return true;
}

//=============================================================================
// DEFAULT VALUE
//=============================================================================
//_____________________________________________________________________________
/**
 * Set the default value.
 *
 * @param aDefaultValue default value to change to.
 * @return Whether or not the default value was changed.
 */
bool SimbodySpeed::setDefaultValue(double aDefaultValue)
{
	_defaultValue = aDefaultValue;
	return true;
}

//=============================================================================
// VALUE
//=============================================================================
//done_____________________________________________________________________________
/**
 * Set the value.
 *
 * @param aValue value to change to.
 * @return Whether or not the value was changed.
 */
bool SimbodySpeed::setValue(double aValue)
{
	_engine->resetBodyAndMobilityForceVectors();
	_engine->_matter->setMobilizerU(*(_engine->_s),_bodyId,_mobilityIndex,aValue);
	_engine->_matter->realize(*(_engine->_s),Stage::Velocity);
	return true;
}

//done_____________________________________________________________________________
/**
 * Get the value.
 *
 * @return The current value of the speed.
 */
double SimbodySpeed::getValue() const
{
	return _engine->_matter->getMobilizerU(*(_engine->_s),_bodyId,_mobilityIndex);

}

//=============================================================================
// ACCELERATION
//=============================================================================
//_____________________________________________________________________________
/**
 * Get the acceleration of this speed.  Note that the accelerations must
 * have been computed by the dynamics engine by calling computeDerivatives()
 * for this method to return a valid result.
 *
 * @return The current value of the acceleration.
 */
double SimbodySpeed::getAcceleration() const
{
	//_engine->_matter->getMobilizerUDot(*(_engine->_s),_bodyId,_mobilityIndex);
	Vector udot = _engine->_matter->getUDot(*(_engine->_s));
	return udot(_bodyId - 1);
}

<commit_msg>Minor changes to the getAcceleration() method.<commit_after>// SimbodySpeed.cpp
// Author: Frank C. Anderson
/*
 * Copyright (c) 2006, Stanford University. All rights reserved.
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//=============================================================================
// INCLUDES
//=============================================================================
#include "SimbodySpeed.h"
#include "SimbodyEngine.h"
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Common/SimmIO.h>
#include <OpenSim/Common/SimmMacros.h>

//=============================================================================
// STATICS
//=============================================================================
using namespace std;
using namespace SimTK;
using namespace OpenSim;

//=============================================================================
// CONSTRUCTOR(S) AND DESTRUCTOR
//=============================================================================
//_____________________________________________________________________________
/**
 * Default constructor.
 */
SimbodySpeed::SimbodySpeed() :
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
}

//_____________________________________________________________________________
/**
 * Destructor.
 */
SimbodySpeed::~SimbodySpeed()
{
}

//_____________________________________________________________________________
/**
 * Copy constructor.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
SimbodySpeed::SimbodySpeed(const SimbodySpeed &aSpeed) :
   AbstractSpeed(aSpeed),
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
	copyData(aSpeed);
}

//_____________________________________________________________________________
/**
 * Copy constructor from an AbstractSpeed.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
SimbodySpeed::SimbodySpeed(const AbstractSpeed &aSpeed) :
   AbstractSpeed(aSpeed),
   _defaultValue(_defaultValueProp.getValueDbl()),
	_coordinateName(_coordinateNameProp.getValueStr())
{
	setNull();
	setupProperties();
	copyData(aSpeed);
}

//_____________________________________________________________________________
/**
 * Copy this speed and return a pointer to the copy.
 * The copy constructor for this class is used.
 *
 * @return Pointer to a copy of this SimbodySpeed.
 */
Object* SimbodySpeed::copy() const
{
	SimbodySpeed *gc = new SimbodySpeed(*this);
	return(gc);
}

//=============================================================================
// CONSTRUCTION METHODS
//=============================================================================
//_____________________________________________________________________________
/**
 * Copy data members from one SimbodySpeed to another.
 *
 * @param aSpeed SimbodySpeed to be copied.
 */
void SimbodySpeed::copyData(const SimbodySpeed &aSpeed)
{
	_defaultValue = aSpeed.getDefaultValue();
	_coordinateName = aSpeed._coordinateName;
	_engine = aSpeed._engine;
}

//_____________________________________________________________________________
/**
 * Copy data members from an AbstractSpeed to an SimbodySpeed.
 *
 * @param aSpeed AbstractSpeed to be copied.
 */
void SimbodySpeed::copyData(const AbstractSpeed &aSpeed)
{
	_defaultValue = aSpeed.getDefaultValue();
	_coordinate = aSpeed.getCoordinate();
	if (_coordinate)
		_coordinateName = _coordinate->getName();
	else
		_coordinateName = "Unassigned";
}

//_____________________________________________________________________________
/**
 * Set the data members of this SimbodySpeed to their null values.
 */
void SimbodySpeed::setNull(void)
{
	setType("SimbodySpeed");

	_coordinate = NULL;
	_engine = NULL;
	_mobilityIndex = -1;
	_engine = NULL;
}

//_____________________________________________________________________________
/**
 * Connect properties to local pointers.
 */
void SimbodySpeed::setupProperties(void)
{
	_defaultValueProp.setName("default_value");
	_defaultValueProp.setValue(0.0);
	_propertySet.append(&_defaultValueProp);

	_coordinateNameProp.setName("coordinate");
	_propertySet.append(&_coordinateNameProp);
}

//_____________________________________________________________________________
/**
 * Perform some set up functions that happen after the
 * object has been deserialized or copied.
 *
 * @param aEngine dynamics engine containing this SimbodySpeed.
 */
void SimbodySpeed::setup(AbstractDynamicsEngine* aEngine)
{
	// Base class;
	AbstractSpeed::setup(aEngine);

	_engine = dynamic_cast<SimbodyEngine*>(aEngine);

	_coordinate = _engine->getCoordinateSet()->get(_coordinateName);

	// If the user specified a default value, set the
	// current value to the default value.
	if (!_defaultValueProp.getUseDefault())
		setValue(_defaultValue);
}

//=============================================================================
// OPERATORS
//=============================================================================
//_____________________________________________________________________________
/**
 * Assignment operator.
 *
 * @return Reference to this object.
 */
SimbodySpeed& SimbodySpeed::operator=(const SimbodySpeed &aSpeed)
{
	// BASE CLASS
	AbstractSpeed::operator=(aSpeed);

	copyData(aSpeed);

	return(*this);
}

//=============================================================================
// COORDINATE
//=============================================================================
//_____________________________________________________________________________
/**
 * Set the coordinate that this speed corresponds to.
 *
 * @param Pointer to the coordinate.
 * @return Whether or not the coordinate was set.
 */
bool SimbodySpeed::setCoordinate(AbstractCoordinate *aCoordinate)
{
	_coordinate = aCoordinate;
	return true;
}
//_____________________________________________________________________________
/**
 * Set the name of the coordinate that this speed corresponds to. When creating
 * a new SimbodySpeed object, this method should be used rather than setCoordinate,
 * because setup() will use _coordinateName to set _coordinate (which needs
 * to be done when deserializing SimbodySpeed objects).
 *
 * @param Name of the coordinate.
 * @return Whether or not the coordinate was set.
 */
bool SimbodySpeed::setCoordinateName(const string& aCoordName)
{
	_coordinateName = aCoordName;
	return true;
}

//=============================================================================
// DEFAULT VALUE
//=============================================================================
//_____________________________________________________________________________
/**
 * Set the default value.
 *
 * @param aDefaultValue default value to change to.
 * @return Whether or not the default value was changed.
 */
bool SimbodySpeed::setDefaultValue(double aDefaultValue)
{
	_defaultValue = aDefaultValue;
	return true;
}

//=============================================================================
// VALUE
//=============================================================================
//done_____________________________________________________________________________
/**
 * Set the value.
 *
 * @param aValue value to change to.
 * @return Whether or not the value was changed.
 */
bool SimbodySpeed::setValue(double aValue)
{
	_engine->resetBodyAndMobilityForceVectors();
	_engine->_matter->setMobilizerU(*(_engine->_s),_bodyId,_mobilityIndex,aValue);
	_engine->_matter->realize(*(_engine->_s),Stage::Velocity);
	return true;
}

//done_____________________________________________________________________________
/**
 * Get the value.
 *
 * @return The current value of the speed.
 */
double SimbodySpeed::getValue() const
{
	return _engine->_matter->getMobilizerU(*(_engine->_s),_bodyId,_mobilityIndex);

}

//=============================================================================
// ACCELERATION
//=============================================================================
//_____________________________________________________________________________
/**
 * Get the acceleration of this speed.  Note that the accelerations must
 * have been computed by the dynamics engine by calling computeDerivatives()
 * for this method to return a valid result.
 *
 * @return The current value of the acceleration.
 */
double SimbodySpeed::getAcceleration() const
{
	//_engine->_matter->getMobilizerUDot(*(_engine->_s),_bodyId,_mobilityIndex);
	Vector udot = _engine->_matter->getUDot(*(_engine->_s));
	//cout<<_coordinateName<<": udot("<<_bodyId-1<<")="<<udot[_bodyId-1]<<endl;
	return udot[_bodyId - 1];
}

<|endoftext|>


<commit_before><commit_msg>Edit comments.<commit_after><|endoftext|>


<commit_before>////////////////////////////////////////////////////////////
//
// DAGON - An Adventure Game Engine
// Copyright (c) 2011-2014 Senscape s.r.l.
// All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
//
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////

#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <sstream>

#include "Config.h"
#include "Font.h"
#include "Language.h"
#include "Log.h"

namespace dagon {

////////////////////////////////////////////////////////////
// Implementation - Constructor
////////////////////////////////////////////////////////////

Font::Font() :
config(Config::instance()),
log(Log::instance())
{
  _isLoaded = false;
  this->setType(kObjectFont);
}

////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////

void Font::clear() {
  if (_isLoaded)
    glDeleteTextures(kMaxChars, _textures);
}

bool Font::isLoaded() {
  return _isLoaded;
}

void Font::print(int x, int y, const char* text, ...) {
  if (_isLoaded) {
    char buffer[kMaxFeedLength];
    va_list ap;

    va_start(ap, text);
    int length = vsnprintf(buffer, kMaxFeedLength, text, ap);
    va_end(ap);

    glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPushMatrix();
    glTranslatef(x, y, 0);

    for (const char* c = buffer; length > 0; c++, length--) {
      int ch = *c;

      GLfloat texCoords[] = { 0, 0, 0, _glyph[ch].y,
        _glyph[ch].x, _glyph[ch].y, _glyph[ch].x, 0 };

      GLshort coords[] = { 0, 0, 0, _glyph[ch].rows,
        _glyph[ch].width, _glyph[ch].rows, _glyph[ch].width, 0 };

      glBindTexture(GL_TEXTURE_2D, _textures[ch]);
      glTranslatef(static_cast<GLfloat>(_glyph[ch].left), 0, 0);
      glPushMatrix();
      glTranslatef(0, -static_cast<GLfloat>(_glyph[ch].top) + _height, 0);
      glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
      glVertexPointer(2, GL_SHORT, 0, coords);
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      glPopMatrix();
      glTranslatef(static_cast<GLfloat>(_glyph[ch].advance >> 6), 0, 0);
    }
    glPopMatrix();
    glPopAttrib();
  }
}

void Font::wPrint(int x, int y, const char* text) {
  if (_isLoaded) {
    size_t origsize = strlen(text) + 1;
    wchar_t wcstring[kMaxFeedLength];
   // setlocale(LC_CTYPE, "en_US.UTF-8");
    mbstowcs(wcstring, text, origsize);
   // setlocale(LC_ALL,"C");

    glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPushMatrix();
    glTranslatef(x, y, 0);

    size_t length = wcslen(wcstring);
    for (const wchar_t* c = wcstring; length > 0; c++, length--) {
      unsigned long ch = *c;
      GLfloat texCoords[] = { 0, 0, 0, _glyph[ch].y,
        _glyph[ch].x, _glyph[ch].y, _glyph[ch].x, 0 };

      GLshort coords[] = { 0, 0, 0, _glyph[ch].rows,
        _glyph[ch].width, _glyph[ch].rows, _glyph[ch].width, 0 };

      glBindTexture(GL_TEXTURE_2D, _textures[ch]);
      glTranslatef(static_cast<GLfloat>(_glyph[ch].left), 0, 0);
      glPushMatrix();
      glTranslatef(0, -static_cast<GLfloat>(_glyph[ch].top) + _height, 0);
      glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
      glVertexPointer(2, GL_SHORT, 0, coords);
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      glPopMatrix();
      glTranslatef(static_cast<GLfloat>(_glyph[ch].advance >> 6), 0, 0);
    }
    glPopMatrix();
    glPopAttrib();
  }
}

// FIXME: This is a repeated method from RenderManager --
//  it would be best to avoid this.
void Font::setColor(uint32_t color) {
  uint8_t b = (color & 0x000000ff);
  uint8_t g = (color & 0x0000ff00) >> 8;
  uint8_t r = (color & 0x00ff0000) >> 16;
  uint8_t a = (color & 0xff000000) >> 24;

  glColor4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f);
}

void Font::setDefault(unsigned int heightOfFont) {
  FT_Face face;

  if (FT_New_Memory_Face(*_library, kFontData, kSizeOfFontData, 0, &face)) {
    log.error(kModFont, "%s", kString15005);
    return;
  }

  _height = heightOfFont;
  _loadFont(face);
  FT_Done_Face(face);
}

void Font::setLibrary(FT_Library* library) {
  _library = library;
}

void Font::setResource(const std::string &fromFileName,
                       unsigned int heightOfFont) {
  FT_Face face;

  if (FT_New_Face(*_library,
                  config.path(kPathResources, fromFileName,
                              kObjectFont).c_str(),
                  0, &face)) {
    log.error(kModFont, "%s: %s", kString15004, fromFileName.c_str());
    return;
  }

  _height = heightOfFont;
  _loadFont(face);
  FT_Done_Face(face);
}

////////////////////////////////////////////////////////////
// Implementation - Private methods
////////////////////////////////////////////////////////////

void Font::_loadFont(FT_Face &face) {
  FT_Set_Char_Size(face, _height << 6, _height << 6, 96, 96);
  glGenTextures(kMaxChars, _textures);

  for (wchar_t ch = 0; ch < kMaxChars; ch++) {
    if (FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT)) {
      log.error(kModFont, "%s: %c", kString15006, ch);
      return;
    }

    FT_Glyph glyph;
    if (FT_Get_Glyph(face->glyph, &glyph)) {
      log.error(kModFont, "%s: %c", kString15007, ch);
      return;
    }

    FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);
    FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
    FT_Bitmap bitmap = bitmapGlyph->bitmap;

    int width = _next(bitmap.width);
    int height = _next(bitmap.rows);
    GLubyte* expandedData;
    expandedData = new GLubyte[2 * width * height];

    for (int j = 0; j < height; j++) {
      for (int i = 0; i < width; i++) {
        expandedData[2 * (i + j * width)] =
        expandedData[2 * (i + j * width) + 1] =
        (i >= bitmap.width || j >= bitmap.rows) ?
        0 : bitmap.buffer[i + bitmap.width * j];
      }
    }

    float x = static_cast<float>(bitmap.width) / static_cast<float>(width);
    float y = static_cast<float>(bitmap.rows) / static_cast<float>(height);
    _glyph[ch] = _makeGlyph(x, y, bitmap, bitmapGlyph, face);

    glBindTexture(GL_TEXTURE_2D, _textures[ch]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 2, width, height, 0,
                 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expandedData);
    delete[] expandedData;
  }
  _isLoaded = true;
}

Glyph Font::_makeGlyph(float x, float y, FT_Bitmap bitmap,
                       FT_BitmapGlyph bitmapGlyph, FT_Face face) {
  Glyph glyph;
  glyph.x = x;
  glyph.y = y;
  glyph.width = bitmap.width;
  glyph.rows = bitmap.rows;
  glyph.left = bitmapGlyph->left;
  glyph.top = bitmapGlyph->top;
  glyph.advance = face->glyph->advance.x;
  return glyph;
}

int Font::_next(int a) {
  int rval = 1;
  while (rval < a) rval <<= 1;
  return rval;
}

}
<commit_msg>Font.cpp: silence g++ sign-compare warning<commit_after>////////////////////////////////////////////////////////////
//
// DAGON - An Adventure Game Engine
// Copyright (c) 2011-2014 Senscape s.r.l.
// All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was
// not distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.
//
////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////

#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <sstream>

#include "Config.h"
#include "Font.h"
#include "Language.h"
#include "Log.h"

namespace dagon {

////////////////////////////////////////////////////////////
// Implementation - Constructor
////////////////////////////////////////////////////////////

Font::Font() :
config(Config::instance()),
log(Log::instance())
{
  _isLoaded = false;
  this->setType(kObjectFont);
}

////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////

void Font::clear() {
  if (_isLoaded)
    glDeleteTextures(kMaxChars, _textures);
}

bool Font::isLoaded() {
  return _isLoaded;
}

void Font::print(int x, int y, const char* text, ...) {
  if (_isLoaded) {
    char buffer[kMaxFeedLength];
    va_list ap;

    va_start(ap, text);
    int length = vsnprintf(buffer, kMaxFeedLength, text, ap);
    va_end(ap);

    glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPushMatrix();
    glTranslatef(x, y, 0);

    for (const char* c = buffer; length > 0; c++, length--) {
      int ch = *c;

      GLfloat texCoords[] = { 0, 0, 0, _glyph[ch].y,
        _glyph[ch].x, _glyph[ch].y, _glyph[ch].x, 0 };

      GLshort coords[] = { 0, 0, 0, _glyph[ch].rows,
        _glyph[ch].width, _glyph[ch].rows, _glyph[ch].width, 0 };

      glBindTexture(GL_TEXTURE_2D, _textures[ch]);
      glTranslatef(static_cast<GLfloat>(_glyph[ch].left), 0, 0);
      glPushMatrix();
      glTranslatef(0, -static_cast<GLfloat>(_glyph[ch].top) + _height, 0);
      glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
      glVertexPointer(2, GL_SHORT, 0, coords);
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      glPopMatrix();
      glTranslatef(static_cast<GLfloat>(_glyph[ch].advance >> 6), 0, 0);
    }
    glPopMatrix();
    glPopAttrib();
  }
}

void Font::wPrint(int x, int y, const char* text) {
  if (_isLoaded) {
    size_t origsize = strlen(text) + 1;
    wchar_t wcstring[kMaxFeedLength];
   // setlocale(LC_CTYPE, "en_US.UTF-8");
    mbstowcs(wcstring, text, origsize);
   // setlocale(LC_ALL,"C");

    glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPushMatrix();
    glTranslatef(x, y, 0);

    size_t length = wcslen(wcstring);
    for (const wchar_t* c = wcstring; length > 0; c++, length--) {
      unsigned long ch = *c;
      GLfloat texCoords[] = { 0, 0, 0, _glyph[ch].y,
        _glyph[ch].x, _glyph[ch].y, _glyph[ch].x, 0 };

      GLshort coords[] = { 0, 0, 0, _glyph[ch].rows,
        _glyph[ch].width, _glyph[ch].rows, _glyph[ch].width, 0 };

      glBindTexture(GL_TEXTURE_2D, _textures[ch]);
      glTranslatef(static_cast<GLfloat>(_glyph[ch].left), 0, 0);
      glPushMatrix();
      glTranslatef(0, -static_cast<GLfloat>(_glyph[ch].top) + _height, 0);
      glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
      glVertexPointer(2, GL_SHORT, 0, coords);
      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      glPopMatrix();
      glTranslatef(static_cast<GLfloat>(_glyph[ch].advance >> 6), 0, 0);
    }
    glPopMatrix();
    glPopAttrib();
  }
}

// FIXME: This is a repeated method from RenderManager --
//  it would be best to avoid this.
void Font::setColor(uint32_t color) {
  uint8_t b = (color & 0x000000ff);
  uint8_t g = (color & 0x0000ff00) >> 8;
  uint8_t r = (color & 0x00ff0000) >> 16;
  uint8_t a = (color & 0xff000000) >> 24;

  glColor4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f);
}

void Font::setDefault(unsigned int heightOfFont) {
  FT_Face face;

  if (FT_New_Memory_Face(*_library, kFontData, kSizeOfFontData, 0, &face)) {
    log.error(kModFont, "%s", kString15005);
    return;
  }

  _height = heightOfFont;
  _loadFont(face);
  FT_Done_Face(face);
}

void Font::setLibrary(FT_Library* library) {
  _library = library;
}

void Font::setResource(const std::string &fromFileName,
                       unsigned int heightOfFont) {
  FT_Face face;

  if (FT_New_Face(*_library,
                  config.path(kPathResources, fromFileName,
                              kObjectFont).c_str(),
                  0, &face)) {
    log.error(kModFont, "%s: %s", kString15004, fromFileName.c_str());
    return;
  }

  _height = heightOfFont;
  _loadFont(face);
  FT_Done_Face(face);
}

////////////////////////////////////////////////////////////
// Implementation - Private methods
////////////////////////////////////////////////////////////

void Font::_loadFont(FT_Face &face) {
  FT_Set_Char_Size(face, _height << 6, _height << 6, 96, 96);
  glGenTextures(kMaxChars, _textures);

  for (wchar_t ch = 0; ch < kMaxChars; ch++) {
    if (FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT)) {
      log.error(kModFont, "%s: %c", kString15006, ch);
      return;
    }

    FT_Glyph glyph;
    if (FT_Get_Glyph(face->glyph, &glyph)) {
      log.error(kModFont, "%s: %c", kString15007, ch);
      return;
    }

    FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);
    FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
    FT_Bitmap bitmap = bitmapGlyph->bitmap;

    uint width = _next(bitmap.width);
    uint height = _next(bitmap.rows);
    GLubyte* expandedData;
    expandedData = new GLubyte[2 * width * height];

    for (uint j = 0; j < height; j++) {
      for (uint i = 0; i < width; i++) {
        expandedData[2 * (i + j * width)] =
        expandedData[2 * (i + j * width) + 1] =
        (i >= bitmap.width || j >= bitmap.rows) ?
        0 : bitmap.buffer[i + bitmap.width * j];
      }
    }

    float x = static_cast<float>(bitmap.width) / static_cast<float>(width);
    float y = static_cast<float>(bitmap.rows) / static_cast<float>(height);
    _glyph[ch] = _makeGlyph(x, y, bitmap, bitmapGlyph, face);

    glBindTexture(GL_TEXTURE_2D, _textures[ch]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 2, width, height, 0,
                 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expandedData);
    delete[] expandedData;
  }
  _isLoaded = true;
}

Glyph Font::_makeGlyph(float x, float y, FT_Bitmap bitmap,
                       FT_BitmapGlyph bitmapGlyph, FT_Face face) {
  Glyph glyph;
  glyph.x = x;
  glyph.y = y;
  glyph.width = bitmap.width;
  glyph.rows = bitmap.rows;
  glyph.left = bitmapGlyph->left;
  glyph.top = bitmapGlyph->top;
  glyph.advance = face->glyph->advance.x;
  return glyph;
}

int Font::_next(int a) {
  int rval = 1;
  while (rval < a) rval <<= 1;
  return rval;
}

}
<|endoftext|>


<commit_before>#include "Grid.hpp"

#include <iostream>

namespace envire { namespace maps
{

Grid::Grid()
    : LocalMap(),
      num_cells(0,0),
      resolution(0,0)
{}

Grid::Grid(const Vector2ui &num_cells, const Eigen::Vector2d &resolution)
    : LocalMap(),
      num_cells(num_cells),
      resolution(resolution)
{}

Grid::Grid(const Vector2ui &num_cells,
            const Vector2d &resolution,
            const boost::shared_ptr<LocalMapData> &data)
    : LocalMap(data),
      num_cells(num_cells),
      resolution(resolution)
{}

Grid::~Grid()
{}

const Vector2ui& Grid::getNumCells() const
{
    return num_cells;
}

const Vector2d& Grid::getResolution() const
{
    return resolution;
}

Vector2d Grid::getSize() const
{
    return resolution.array() * num_cells.cast<double>().array();
}

bool Grid::inGrid(const Index& idx) const
{
    // do not need to check idx against (0,0),
    // until idx is of type unsigned int
    return idx < Index(num_cells);
}

bool Grid::fromGrid(const Index& idx, Vector3d& pos) const
{
    /** Index inside the grid **/
    if (inGrid(idx))
    {
        // position at the cell center without offset trnasformation
        Vector2d center = (idx.cast<double>() + Vector2d(0.5, 0.5)).array() * resolution.array();

        // Apply the offset transformation to the obtained position
        pos = this->getOffset() * Vector3d(center.x(), center.y(), 0.);
        return true;
    } else
    {
        /** Index outside the grid **/
        return false;
    }
}

bool Grid::fromGrid(const Index& idx, Vector3d& pos_in_frame, const base::Transform3d &frame_in_grid) const
{
    Vector3d pos_in_map;

    if (fromGrid(idx, pos_in_map) == false)
        return false;

    pos_in_frame = frame_in_grid.inverse() * pos_in_map;

    return true;
}

bool Grid::toGrid(const Vector3d& pos, Index& idx, Vector3d &pos_diff) const
{
    // position without offset
    Vector2d pos_temp = (this->getOffset().inverse() * pos).head<2>();

    // cast to float due to position which lies on the border between two cells
    Eigen::Vector2d idx_double = pos_temp.array() / resolution.array();
    Index idx_temp(std::floor(idx_double.x()), std::floor(idx_double.y()));

    Vector3d center;
    if(inGrid(idx_temp) && fromGrid(idx_temp, center))
    {
        idx = idx_temp;
        pos_diff = pos - center;
        return true;
    }
    else {
        return false;
    }
}

bool Grid::toGrid(const Vector3d& pos_in_frame, Index& idx, const base::Transform3d &frame_in_grid) const
{
    Eigen::Vector3d pos_in_map = frame_in_grid * pos_in_frame;
    Eigen::Vector3d pos_diff;
    return toGrid(pos_in_map, idx, pos_diff);
}

bool Grid::toGrid(const Vector3d& pos, Index& idx) const
{
    Vector3d pos_diff;
    return toGrid(pos, idx, pos_diff);
}

}}
<commit_msg>src: adapt Grid class to the LocalMap method (localFrame)<commit_after>#include "Grid.hpp"

#include <iostream>

namespace envire { namespace maps
{

Grid::Grid()
    : LocalMap(),
      num_cells(0,0),
      resolution(0,0)
{}

Grid::Grid(const Vector2ui &num_cells, const Eigen::Vector2d &resolution)
    : LocalMap(),
      num_cells(num_cells),
      resolution(resolution)
{}

Grid::Grid(const Vector2ui &num_cells,
            const Vector2d &resolution,
            const boost::shared_ptr<LocalMapData> &data)
    : LocalMap(data),
      num_cells(num_cells),
      resolution(resolution)
{}

Grid::~Grid()
{}

const Vector2ui& Grid::getNumCells() const
{
    return num_cells;
}

const Vector2d& Grid::getResolution() const
{
    return resolution;
}

Vector2d Grid::getSize() const
{
    return resolution.array() * num_cells.cast<double>().array();
}

bool Grid::inGrid(const Index& idx) const
{
    // do not need to check idx against (0,0),
    // until idx is of type unsigned int
    return idx < Index(num_cells);
}

bool Grid::fromGrid(const Index& idx, Vector3d& pos) const
{
    /** Index inside the grid **/
    if (inGrid(idx))
    {
        // position at the cell center without offset trnasformation
        Vector2d center = (idx.cast<double>() + Vector2d(0.5, 0.5)).array() * resolution.array();

        // Apply the offset transformation to the obtained position
        pos = this->localFrame() * Vector3d(center.x(), center.y(), 0.);
        return true;
    } else
    {
        /** Index outside the grid **/
        return false;
    }
}

bool Grid::fromGrid(const Index& idx, Vector3d& pos_in_frame, const base::Transform3d &frame_in_grid) const
{
    Vector3d pos_in_map;

    if (fromGrid(idx, pos_in_map) == false)
        return false;

    pos_in_frame = frame_in_grid.inverse() * pos_in_map;

    return true;
}

bool Grid::toGrid(const Vector3d& pos, Index& idx, Vector3d &pos_diff) const
{
    // position without offset
    Vector2d pos_temp = (this->localFrame().inverse() * pos).head<2>();

    // cast to float due to position which lies on the border between two cells
    Eigen::Vector2d idx_double = pos_temp.array() / resolution.array();
    Index idx_temp(std::floor(idx_double.x()), std::floor(idx_double.y()));

    Vector3d center;
    if(inGrid(idx_temp) && fromGrid(idx_temp, center))
    {
        idx = idx_temp;
        pos_diff = pos - center;
        return true;
    }
    else {
        return false;
    }
}

bool Grid::toGrid(const Vector3d& pos_in_frame, Index& idx, const base::Transform3d &frame_in_grid) const
{
    Eigen::Vector3d pos_in_map = frame_in_grid * pos_in_frame;
    Eigen::Vector3d pos_diff;
    return toGrid(pos_in_map, idx, pos_diff);
}

bool Grid::toGrid(const Vector3d& pos, Index& idx) const
{
    Vector3d pos_diff;
    return toGrid(pos, idx, pos_diff);
}

}}
<|endoftext|>