<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/elementaryFluxModes/CEFMTask.cpp,v $
//   $Revision: 1.5 $
//   $Name:  $
//   $Author: tjohann $
//   $Date: 2008/07/02 08:06:12 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CEFMTask class.
 *
 * This class implements a optimization task which is comprised of a
 * of a problem and a method.
 *
 */
#include "copasi.h"

#include "CEFMTask.h"
#include "CEFMMethod.h"
#include "CEFMProblem.h"

#ifdef COPASI_SSA
#include "CSSAMethod.h"
#endif

#include "model/CModel.h"
#include "model/CChemEqInterface.h"
#include "utilities/CCopasiProblem.h"

const unsigned C_INT32 CEFMTask::ValidMethods[] =
  {
    CCopasiMethod::EFMAlgorithm,
#ifdef COPASI_SSA
    CCopasiMethod::stoichiometricStabilityAnalysis,
#endif
    0
  };

CEFMTask::CEFMTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::fluxMode, pParent)
{
  mpProblem = new CEFMProblem(this);
  mpMethod = CEFMMethod::createMethod();

  this->add(mpMethod, true);
}

CEFMTask::CEFMTask(const CEFMTask & src,
                   const CCopasiContainer * pParent):
    CCopasiTask(src, pParent)
{
  mpProblem = new CCopasiProblem(*static_cast< CEFMProblem * >(src.mpProblem), this);
  mpMethod = CEFMMethod::createMethod(src.mpMethod->getSubType());

  this->add(mpMethod, true);
}

CEFMTask::~CEFMTask()
{}

bool CEFMTask::setCallBack(CProcessReport * pCallBack)
{
  bool success = CCopasiTask::setCallBack(pCallBack);

  if (!mpProblem->setCallBack(pCallBack)) success = false;
  if (!mpMethod->setCallBack(pCallBack)) success = false;

  return success;
}

bool CEFMTask::initialize(const OutputFlag & of,
                          COutputHandler * pOutputHandler,
                          std::ostream * pOstream)
{
  CEFMMethod * pMethod = dynamic_cast<CEFMMethod *>(mpMethod);
  if (pMethod == NULL) return false;

  return CCopasiTask::initialize(of, pOutputHandler, pOstream);
}

bool CEFMTask::process(const bool & /* useInitialValues */)
{
  return static_cast<CEFMMethod *>(mpMethod)->calculate();
}

bool CEFMTask::setMethodType(const int & type)
{
  CCopasiMethod::SubType Type = (CCopasiMethod::SubType) type;

  if (mpMethod->getSubType() == Type) return true;

  pdelete (mpMethod);

  mpMethod = CEFMMethod::createMethod(Type);
  this->add(mpMethod, true);

  return true;
}

bool CEFMTask::isFluxModeReversible(unsigned C_INT32 index) const
{return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index].isReversible();}

//const CFluxMode & CElementaryFluxModes::getFluxMode(unsigned C_INT32 index) const
//  {return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index];}

std::string
CEFMTask::getFluxModeDescription(unsigned C_INT32 index) const
  {
    std::stringstream tmp;
    const std::vector< CFluxMode > & FluxModes =
      static_cast<CEFMMethod *>(mpMethod)->getFluxModes();
    const CVector< unsigned C_INT32 > & Index =
      static_cast<CEFMMethod *>(mpMethod)->getIndex();

    unsigned C_INT32 j, jmax = FluxModes[index].size();
    const CCopasiVectorNS< CReaction > & Reactions = mpProblem->getModel()->getReactions();

#ifdef COPASI_SSA
    if (mpMethod->getSubType() == CCopasiMethod::stoichiometricStabilityAnalysis)
      {
        CSSAMethod * method = dynamic_cast<CSSAMethod *>(mpMethod);

        for (j = 0; j < jmax; j++)
          {
            if (j) tmp << "\n";
            std::string addstrng = "";
            if (Reactions[Index[FluxModes[index].getReactionIndex(j)]]->isReversible())
              {
                addstrng = " (Forward)";
                if (method->isReactionReversed(FluxModes[index].getReactionIndex(j)))
                  addstrng = " (Backward)";
              }

            tmp << FluxModes[index].getMultiplier(j) << " * "
            << Reactions[Index[FluxModes[index].getReactionIndex(j)]]->getObjectName()
            << addstrng;
          }
      }
    else
#endif
      for (j = 0; j < jmax; j++)
        {
          if (j) tmp << "\n";
          tmp << FluxModes[index].getMultiplier(j) << " * "
          << Reactions[Index[FluxModes[index].getReactionIndex(j)]]->getObjectName();
        }

    return tmp.str();
  }

unsigned C_INT32 CEFMTask::getFluxModeSize() const
{return static_cast<CEFMMethod *>(mpMethod)->getFluxModes().size();}

unsigned C_INT32 CEFMTask::getFluxModeSize(unsigned C_INT32 index) const
  {return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index].size();}

std::string CEFMTask::getReactionEquation(unsigned C_INT32 index1, unsigned C_INT32 index2) const
  {
    const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
    CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

#ifdef COPASI_SSA
    if (mpMethod->getSubType() == CCopasiMethod::stoichiometricStabilityAnalysis)
      {
        CSSAMethod * method = dynamic_cast<CSSAMethod *>(mpMethod);

        std::string retstring = getReactionEquationForward(index1, index2);

        if (Reaction.isReversible())
          {
            if (method->isReactionReversed(static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)))
              retstring = getReactionEquationBackward(index1, index2);
          }

        return retstring;
      }
    else
#endif //COPASI_SSA
      return CChemEqInterface::getChemEqString(mpProblem->getModel(),
          *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]],
          false);
  }

#ifdef COPASI_SSA
std::string CEFMTask::getReactionEquationForward(unsigned C_INT32 index1, unsigned C_INT32 index2) const
  {
    const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
    CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

    std::string equation = CChemEqInterface::getChemEqString(mpProblem->getModel(),
                           Reaction,
                           false);

    if (Reaction.isReversible())
      {
        int i = equation.find("=", 0);
        equation.replace(i, 1, "->");
      }

    return equation;
  }

std::string CEFMTask::getReactionEquationBackward(unsigned C_INT32 index1, unsigned C_INT32 index2) const
  {
    const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
    CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

    std::string equation = CChemEqInterface::getChemEqString(mpProblem->getModel(),
                           Reaction,
                           false);

    if (Reaction.isReversible())
      {
        int i = equation.find("=", 0);
        std::string lhs = equation.substr(0, i - 1);
        std::string rhs = equation.substr(i + 2 , equation.size() - i - 1);
        equation = rhs + " -> " + lhs;
      }

    return equation;
  }
#endif // COPASI_SSA
<commit_msg>Fixed Bug 1232. The format for the multipliers has been changed to show integers.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/elementaryFluxModes/CEFMTask.cpp,v $
//   $Revision: 1.6 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2009/06/24 16:43:11 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CEFMTask class.
 *
 * This class implements a optimization task which is comprised of a
 * of a problem and a method.
 *
 */
#include "copasi.h"

#include "CEFMTask.h"
#include "CEFMMethod.h"
#include "CEFMProblem.h"

#ifdef COPASI_SSA
#include "CSSAMethod.h"
#endif

#include "model/CModel.h"
#include "model/CChemEqInterface.h"
#include "utilities/CCopasiProblem.h"

const unsigned C_INT32 CEFMTask::ValidMethods[] =
{
  CCopasiMethod::EFMAlgorithm,
#ifdef COPASI_SSA
  CCopasiMethod::stoichiometricStabilityAnalysis,
#endif
  0
};

CEFMTask::CEFMTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::fluxMode, pParent)
{
  mpProblem = new CEFMProblem(this);
  mpMethod = CEFMMethod::createMethod();

  this->add(mpMethod, true);
}

CEFMTask::CEFMTask(const CEFMTask & src,
                   const CCopasiContainer * pParent):
    CCopasiTask(src, pParent)
{
  mpProblem = new CCopasiProblem(*static_cast< CEFMProblem * >(src.mpProblem), this);
  mpMethod = CEFMMethod::createMethod(src.mpMethod->getSubType());

  this->add(mpMethod, true);
}

CEFMTask::~CEFMTask()
{}

bool CEFMTask::setCallBack(CProcessReport * pCallBack)
{
  bool success = CCopasiTask::setCallBack(pCallBack);

  if (!mpProblem->setCallBack(pCallBack)) success = false;

  if (!mpMethod->setCallBack(pCallBack)) success = false;

  return success;
}

bool CEFMTask::initialize(const OutputFlag & of,
                          COutputHandler * pOutputHandler,
                          std::ostream * pOstream)
{
  CEFMMethod * pMethod = dynamic_cast<CEFMMethod *>(mpMethod);

  if (pMethod == NULL) return false;

  return CCopasiTask::initialize(of, pOutputHandler, pOstream);
}

bool CEFMTask::process(const bool & /* useInitialValues */)
{
  return static_cast<CEFMMethod *>(mpMethod)->calculate();
}

bool CEFMTask::setMethodType(const int & type)
{
  CCopasiMethod::SubType Type = (CCopasiMethod::SubType) type;

  if (mpMethod->getSubType() == Type) return true;

  pdelete(mpMethod);

  mpMethod = CEFMMethod::createMethod(Type);
  this->add(mpMethod, true);

  return true;
}

bool CEFMTask::isFluxModeReversible(unsigned C_INT32 index) const
{return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index].isReversible();}

//const CFluxMode & CElementaryFluxModes::getFluxMode(unsigned C_INT32 index) const
//  {return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index];}

std::string
CEFMTask::getFluxModeDescription(unsigned C_INT32 index) const
{
  std::stringstream tmp;
  tmp.flags(std::ios::fixed);
  tmp.precision(0);

  const std::vector< CFluxMode > & FluxModes =
    static_cast<CEFMMethod *>(mpMethod)->getFluxModes();
  const CVector< unsigned C_INT32 > & Index =
    static_cast<CEFMMethod *>(mpMethod)->getIndex();

  unsigned C_INT32 j, jmax = FluxModes[index].size();
  const CCopasiVectorNS< CReaction > & Reactions = mpProblem->getModel()->getReactions();

#ifdef COPASI_SSA

  if (mpMethod->getSubType() == CCopasiMethod::stoichiometricStabilityAnalysis)
    {
      CSSAMethod * method = dynamic_cast<CSSAMethod *>(mpMethod);

      for (j = 0; j < jmax; j++)
        {
          if (j) tmp << "\n";

          std::string addstrng = "";

          if (Reactions[Index[FluxModes[index].getReactionIndex(j)]]->isReversible())
            {
              addstrng = " (Forward)";

              if (method->isReactionReversed(FluxModes[index].getReactionIndex(j)))
                addstrng = " (Backward)";
            }

          tmp << FluxModes[index].getMultiplier(j) << " * "
          << Reactions[Index[FluxModes[index].getReactionIndex(j)]]->getObjectName()
          << addstrng;
        }
    }
  else
#endif
    for (j = 0; j < jmax; j++)
      {
        if (j) tmp << "\n";

        tmp << FluxModes[index].getMultiplier(j) << " * "
        << Reactions[Index[FluxModes[index].getReactionIndex(j)]]->getObjectName();
      }

  return tmp.str();
}

unsigned C_INT32 CEFMTask::getFluxModeSize() const
{return static_cast<CEFMMethod *>(mpMethod)->getFluxModes().size();}

unsigned C_INT32 CEFMTask::getFluxModeSize(unsigned C_INT32 index) const
{return static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index].size();}

std::string CEFMTask::getReactionEquation(unsigned C_INT32 index1, unsigned C_INT32 index2) const
{
  const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
  CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

#ifdef COPASI_SSA

  if (mpMethod->getSubType() == CCopasiMethod::stoichiometricStabilityAnalysis)
    {
      CSSAMethod * method = dynamic_cast<CSSAMethod *>(mpMethod);

      std::string retstring = getReactionEquationForward(index1, index2);

      if (Reaction.isReversible())
        {
          if (method->isReactionReversed(static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)))
            retstring = getReactionEquationBackward(index1, index2);
        }

      return retstring;
    }
  else
#endif //COPASI_SSA
    return CChemEqInterface::getChemEqString(mpProblem->getModel(),
           *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]],
           false);
}

#ifdef COPASI_SSA
std::string CEFMTask::getReactionEquationForward(unsigned C_INT32 index1, unsigned C_INT32 index2) const
{
  const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
  CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

  std::string equation = CChemEqInterface::getChemEqString(mpProblem->getModel(),
                         Reaction,
                         false);

  if (Reaction.isReversible())
    {
      int i = equation.find("=", 0);
      equation.replace(i, 1, "->");
    }

  return equation;
}

std::string CEFMTask::getReactionEquationBackward(unsigned C_INT32 index1, unsigned C_INT32 index2) const
{
  const CCopasiVectorNS < CReaction > & Reactions = mpProblem->getModel()->getReactions();
  CReaction Reaction = *Reactions[static_cast<CEFMMethod *>(mpMethod)->getIndex()[static_cast<CEFMMethod *>(mpMethod)->getFluxModes()[index1].getReactionIndex(index2)]];

  std::string equation = CChemEqInterface::getChemEqString(mpProblem->getModel(),
                         Reaction,
                         false);

  if (Reaction.isReversible())
    {
      int i = equation.find("=", 0);
      std::string lhs = equation.substr(0, i - 1);
      std::string rhs = equation.substr(i + 2 , equation.size() - i - 1);
      equation = rhs + " -> " + lhs;
    }

  return equation;
}
#endif // COPASI_SSA
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunctionParameters.cpp,v $
//   $Revision: 1.41 $
//   $Name:  $
//   $Author: ssahle $
//   $Date: 2007/03/09 09:56:18 $
// End CVS Header

// Copyright (C) 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CFunctionParameters
 *
 * Created for Copasi by Stefan Hoops
 * (C) Stefan Hoops 2001
 */

#include "copasi.h"
#include "CFunctionParameters.h"
#include "utilities/CCopasiException.h"

CFunctionParameters::CFunctionParameters(const std::string & name,
    const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Variable Description"),
    mParameters("Variables", this)
{CONSTRUCTOR_TRACE;}

CFunctionParameters::CFunctionParameters(const CFunctionParameters & src,
    const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mParameters(src.mParameters, this)
{CONSTRUCTOR_TRACE;}

CFunctionParameters::~CFunctionParameters() {DESTRUCTOR_TRACE;}

void CFunctionParameters::cleanup()
{
  mParameters.cleanup();
}

CFunctionParameters & CFunctionParameters::operator=(const CFunctionParameters & src)
{
  mParameters.deepCopy(src.mParameters);
  return *this;
}

void CFunctionParameters::add(const CFunctionParameter & parameter)
{
  mParameters.add(parameter);
}

bool CFunctionParameters::add(CFunctionParameter * parameter,
                              const bool & adopt)
{
  mParameters.add(parameter, adopt);

  return true;
}

bool CFunctionParameters::add(const std::string & name,
                              const CFunctionParameter::DataType & type,
                              CFunctionParameter::Role usage)
{
  unsigned C_INT32 Index = mParameters.getIndex(name);

  if (Index != C_INVALID_INDEX)
    return false;

  CFunctionParameter *parameter =
    new CFunctionParameter(name, type, usage);
  mParameters.add(parameter, true);

  return true;
}

void CFunctionParameters::remove(const std::string & name)
{
  mParameters.remove(name);
}

CFunctionParameter * CFunctionParameters::operator[](unsigned C_INT32 index)
{return mParameters[index];}

const CFunctionParameter * CFunctionParameters::operator[](unsigned C_INT32 index) const
  {return mParameters[index];}

CFunctionParameter * CFunctionParameters::operator[](const std::string &name)
{return mParameters[name];}

const CFunctionParameter * CFunctionParameters::operator[](const std::string &name) const
  {return mParameters[name];}

unsigned C_INT32 CFunctionParameters::size() const {return mParameters.size();}

void CFunctionParameters::swap(const unsigned C_INT32 & from, const unsigned C_INT32 & to)
{mParameters.swap(from, to);}

const CFunctionParameter *
CFunctionParameters::getParameterByUsage(CFunctionParameter::Role usage,
    unsigned C_INT32 & pos) const
  {
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = pos; i < imax; i++)
      if (mParameters[i]->getUsage() == usage)
        {
          pos = i + 1;
          return mParameters[i];
        }

    CCopasiMessage(CCopasiMessage::WARNING,
                   MCFunctionParameters + 2,
                   CFunctionParameter::RoleNameDisplay[usage].c_str(), pos);

    return NULL;
  }

unsigned C_INT32 CFunctionParameters::getNumberOfParametersByUsage(CFunctionParameter::Role usage) const
  {
    unsigned C_INT32 i, imax = mParameters.size();
    unsigned C_INT32 count = 0;

    for (i = 0; i < imax; i++)
      if (mParameters[i]->getUsage() == usage) ++count;

    return count;
  }

unsigned C_INT32 CFunctionParameters::findParameterByName(const std::string & name,
    CFunctionParameter::DataType & dataType) const
  {
    //std::string VectorName = name.substr(0, name.find_last_of('_'));
    std::string Name;
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = 0; i < imax; i++)
      {
        Name = mParameters[i]->getObjectName();

        if (Name == name)
          {
            dataType = mParameters[i]->getType();
            return i;
          }
      }

    return C_INVALID_INDEX;
  }

bool CFunctionParameters::isVector(CFunctionParameter::Role role) const
  {
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = 0; i < imax; i++)
      if (mParameters[i]->getUsage() == role)
        return mParameters[i]->getType() >= CFunctionParameter::VINT32;
    //this assumes that if a parameter is not a vector then there
    //will not be a vector parameter with the same role.
    return false;
  }

bool CFunctionParameters::operator==(const CFunctionParameters & rhs) const
  {
    if (size() != rhs.size()) return false;

    C_INT32 i, imax = size();
    for (i = 0; i < imax; ++i)
      {
        if (mParameters[i]->getObjectName() != rhs.mParameters[i]->getObjectName()) return false;
        if (mParameters[i]->getType() != rhs.mParameters[i]->getType()) return false;
        if (mParameters[i]->getUsage() != rhs.mParameters[i]->getUsage()) return false;
      }
    return true;
  }

std::ostream & operator<<(std::ostream &os, const CFunctionParameters & d)
{
  //os << "++++CFunctionParameters: " << std::endl;
  //os << "    CFunctionParameters.mParameters " << std::endl << d.mParameters;
  //os << "----CFunctionParameters " << std::endl;

  C_INT32 i, imax = d.mParameters.size();
  for (i = 0; i < imax; ++i)
    {
      if (0 == i)
        os << "  (";
      else
        os << "    ";

      os << *d.mParameters[i];

      if (imax - 1 == i)
        os << ")\n";
      else
        os << ",\n";
    }

  return os;
}
<commit_msg>The roles VARIABLE and PARAMETER are now handle as equal during compare.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/function/CFunctionParameters.cpp,v $
//   $Revision: 1.42 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2007/10/12 18:30:56 $
// End CVS Header

// Copyright (C) 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CFunctionParameters
 *
 * Created for Copasi by Stefan Hoops
 * (C) Stefan Hoops 2001
 */

#include "copasi.h"
#include "CFunctionParameters.h"
#include "utilities/CCopasiException.h"

CFunctionParameters::CFunctionParameters(const std::string & name,
    const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Variable Description"),
    mParameters("Variables", this)
{CONSTRUCTOR_TRACE;}

CFunctionParameters::CFunctionParameters(const CFunctionParameters & src,
    const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mParameters(src.mParameters, this)
{CONSTRUCTOR_TRACE;}

CFunctionParameters::~CFunctionParameters() {DESTRUCTOR_TRACE;}

void CFunctionParameters::cleanup()
{
  mParameters.cleanup();
}

CFunctionParameters & CFunctionParameters::operator=(const CFunctionParameters & src)
{
  mParameters.deepCopy(src.mParameters);
  return *this;
}

void CFunctionParameters::add(const CFunctionParameter & parameter)
{
  mParameters.add(parameter);
}

bool CFunctionParameters::add(CFunctionParameter * parameter,
                              const bool & adopt)
{
  mParameters.add(parameter, adopt);

  return true;
}

bool CFunctionParameters::add(const std::string & name,
                              const CFunctionParameter::DataType & type,
                              CFunctionParameter::Role usage)
{
  unsigned C_INT32 Index = mParameters.getIndex(name);

  if (Index != C_INVALID_INDEX)
    return false;

  CFunctionParameter *parameter =
    new CFunctionParameter(name, type, usage);
  mParameters.add(parameter, true);

  return true;
}

void CFunctionParameters::remove(const std::string & name)
{
  mParameters.remove(name);
}

CFunctionParameter * CFunctionParameters::operator[](unsigned C_INT32 index)
{return mParameters[index];}

const CFunctionParameter * CFunctionParameters::operator[](unsigned C_INT32 index) const
  {return mParameters[index];}

CFunctionParameter * CFunctionParameters::operator[](const std::string &name)
{return mParameters[name];}

const CFunctionParameter * CFunctionParameters::operator[](const std::string &name) const
  {return mParameters[name];}

unsigned C_INT32 CFunctionParameters::size() const {return mParameters.size();}

void CFunctionParameters::swap(const unsigned C_INT32 & from, const unsigned C_INT32 & to)
{mParameters.swap(from, to);}

const CFunctionParameter *
CFunctionParameters::getParameterByUsage(CFunctionParameter::Role usage,
    unsigned C_INT32 & pos) const
  {
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = pos; i < imax; i++)
      if (mParameters[i]->getUsage() == usage)
        {
          pos = i + 1;
          return mParameters[i];
        }

    CCopasiMessage(CCopasiMessage::WARNING,
                   MCFunctionParameters + 2,
                   CFunctionParameter::RoleNameDisplay[usage].c_str(), pos);

    return NULL;
  }

unsigned C_INT32 CFunctionParameters::getNumberOfParametersByUsage(CFunctionParameter::Role usage) const
  {
    unsigned C_INT32 i, imax = mParameters.size();
    unsigned C_INT32 count = 0;

    for (i = 0; i < imax; i++)
      if (mParameters[i]->getUsage() == usage) ++count;

    return count;
  }

unsigned C_INT32 CFunctionParameters::findParameterByName(const std::string & name,
    CFunctionParameter::DataType & dataType) const
  {
    //std::string VectorName = name.substr(0, name.find_last_of('_'));
    std::string Name;
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = 0; i < imax; i++)
      {
        Name = mParameters[i]->getObjectName();

        if (Name == name)
          {
            dataType = mParameters[i]->getType();
            return i;
          }
      }

    return C_INVALID_INDEX;
  }

bool CFunctionParameters::isVector(CFunctionParameter::Role role) const
  {
    unsigned C_INT32 i, imax = mParameters.size();

    for (i = 0; i < imax; i++)
      if (mParameters[i]->getUsage() == role)
        return mParameters[i]->getType() >= CFunctionParameter::VINT32;
    //this assumes that if a parameter is not a vector then there
    //will not be a vector parameter with the same role.
    return false;
  }

bool CFunctionParameters::operator==(const CFunctionParameters & rhs) const
  {
    if (size() != rhs.size()) return false;

    CFunctionParameter::Role lhsRole, rhsRole;

    C_INT32 i, imax = size();
    for (i = 0; i < imax; ++i)
      {
        if (mParameters[i]->getObjectName() != rhs.mParameters[i]->getObjectName()) return false;
        if (mParameters[i]->getType() != rhs.mParameters[i]->getType()) return false;
        lhsRole = mParameters[i]->getUsage();
        rhsRole = rhs.mParameters[i]->getUsage();

        // We do not destinguish between PARAMETER and VARIABLE
        if ((lhsRole == CFunctionParameter::PARAMETER || lhsRole == CFunctionParameter::VARIABLE) &&
            (rhsRole == CFunctionParameter::PARAMETER || rhsRole == CFunctionParameter::VARIABLE))
          continue;

        if (lhsRole != rhsRole) return false;
      }
    return true;
  }

std::ostream & operator<<(std::ostream &os, const CFunctionParameters & d)
{
  //os << "++++CFunctionParameters: " << std::endl;
  //os << "    CFunctionParameters.mParameters " << std::endl << d.mParameters;
  //os << "----CFunctionParameters " << std::endl;

  C_INT32 i, imax = d.mParameters.size();
  for (i = 0; i < imax; ++i)
    {
      if (0 == i)
        os << "  (";
      else
        os << "    ";

      os << *d.mParameters[i];

      if (imax - 1 == i)
        os << ")\n";
      else
        os << ",\n";
    }

  return os;
}
<|endoftext|>


<commit_before><commit_msg>coverity#708559 Uninitialized pointer field<commit_after><|endoftext|>


<commit_before>/* ---------------------------------------------------------------------
 *
 * Copyright (C) 2013 - 2015 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE at
 * the top level of the deal.II distribution.
 *
 * ---------------------------------------------------------------------

 *
 * Author: Timo Heister, Texas A&M University, 2013
 */

// This tutorial program is odd in the sense that, unlike for most other
// steps, the introduction already provides most of the information on how to
// use the various strategies to generate meshes. Consequently, there is
// little that remains to be commented on here, and we intersperse the code
// with relatively little text. In essence, the code here simply provides a
// reference implementation of what has already been described in the
// introduction.

// @sect3{Include files}

#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_in.h>

#include <iostream>
#include <fstream>

#include <map>

using namespace dealii;

// @sect3{Generating output for a given mesh}

// The following function generates some output for any of the meshes we will
// be generating in the remainder of this program. In particular, it generates
// the following information:
//
// - Some general information about the number of space dimensions in which
//   this mesh lives and its number of cells.
// - The number of boundary faces that use each boundary indicator, so that
//   it can be compared with what we expect.
//
// Finally, the function outputs the mesh in encapsulated postscript (EPS)
// format that can easily be visualized in the same way as was done in step-1.
template<int dim>
void mesh_info(const Triangulation<dim> &tria,
               const std::string        &filename)
{
  std::cout << "Mesh info:" << std::endl
            << " dimension: " << dim << std::endl
            << " no. of cells: " << tria.n_active_cells() << std::endl;

  // Next loop over all faces of all cells and find how often each
  // boundary indicator is used (recall that if you access an element
  // of a std::map object that doesn't exist, it is implicitly created
  // and default initialized -- to zero, in the current case -- before
  // we then increment it):
  {
    std::map<unsigned int, unsigned int> boundary_count;
    typename Triangulation<dim>::active_cell_iterator
    cell = tria.begin_active(),
    endc = tria.end();
    for (; cell!=endc; ++cell)
      {
        for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
          {
            if (cell->face(face)->at_boundary())
              boundary_count[cell->face(face)->boundary_id()]++;
          }
      }

    std::cout << " boundary indicators: ";
    for (std::map<unsigned int, unsigned int>::iterator it=boundary_count.begin();
         it!=boundary_count.end();
         ++it)
      {
        std::cout << it->first << "(" << it->second << " times) ";
      }
    std::cout << std::endl;
  }

  // Finally, produce a graphical representation of the mesh to an output
  // file:
  std::ofstream out (filename.c_str());
  GridOut grid_out;
  grid_out.write_eps (tria, out);
  std::cout << " written to " << filename
            << std::endl
            << std::endl;
}

// @sect3{Main routines}

// @sect4{grid_1: Loading a mesh generated by gmsh}

// In this first example, we show how to load the mesh for which we have
// discussed in the introduction how to generate it. This follows the same
// pattern as used in step-5 to load a mesh, although there it was written in
// a different file format (UCD instead of MSH).
void grid_1 ()
{
  Triangulation<2> triangulation;

  GridIn<2> gridin;
  gridin.attach_triangulation(triangulation);
  std::ifstream f("untitled.msh");
  gridin.read_msh(f);

  mesh_info(triangulation, "grid-1.eps");

}

// @sect4{grid_2: Merging triangulations}

// Here, we first create two triangulations and then merge them into one.  As
// discussed in the introduction, it is important to ensure that the vertices
// at the common interface are located at the same coordinates.
void grid_2 ()
{
  Triangulation<2> tria1;
  GridGenerator::hyper_cube_with_cylindrical_hole (tria1, 0.25, 1.0);

  Triangulation<2> tria2;
  std::vector< unsigned int > repetitions(2);
  repetitions[0]=3;
  repetitions[1]=2;
  GridGenerator::subdivided_hyper_rectangle (tria2, repetitions,
                                             Point<2>(1.0,-1.0),
                                             Point<2>(4.0,1.0));

  Triangulation<2> triangulation;
  GridGenerator::merge_triangulations (tria1, tria2, triangulation);

  mesh_info(triangulation, "grid-2.eps");
}

// @sect4{grid_3: Moving vertices}

// In this function, we move vertices of a mesh. This is simpler than one
// usually expects: if you ask a cell using cell-@>vertex(i) for
// the coordinates of its ith vertex, it doesn't just provide the
// location of this vertex but in fact a reference to the location where these
// coordinates are stored. We can then modify the value stored there.
//
// So this is what we do in the first part of this function: We create a
// square of geometry $[-1,1]^2$ with a circular hole with radius 0.25 located
// at the origin. We then loop over all cells and all vertices and if a vertex
// has a $y$ coordinate equal to one, we move it upward by 0.5.
//
// Note that this sort of procedure does not usually work this way because one
// will typically encounter the same vertices multiple times and may move them
// more than once. It works here because we select the vertices we want to use
// based on their geometric location, and a vertex moved once will fail this
// test in the future. A more general approach to this problem would have been
// to keep a std::set of of those vertex indices that we have already moved
// (which we can obtain using cell-@>vertex_index(i) and only
// move those vertices whose index isn't in the set yet.
void grid_3 ()
{
  Triangulation<2> triangulation;
  GridGenerator::hyper_cube_with_cylindrical_hole (triangulation, 0.25, 1.0);

  Triangulation<2>::active_cell_iterator
  cell = triangulation.begin_active(),
  endc = triangulation.end();
  for (; cell!=endc; ++cell)
    {
      for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
        {
          Point<2> &v = cell->vertex(i);
          if (std::abs(v(1)-1.0)<1e-5)
            v(1) += 0.5;
        }
    }

  // In the second step we will refine the mesh twice. To do this
  // correctly, we have to associate a geometry object with the
  // boundary of the hole; since the boundary of the hole has boundary
  // indicator 1 (see the documentation of the function that generates
  // the mesh), we need to create an object that describes a spherical
  // manifold (i.e., a hyper ball) with appropriate center and assign
  // it to the triangulation. Notice that the function that generates
  // the triangulation sets the boundary indicators of the inner mesh,
  // but leaves unchanged the manifold indicator. We copy the boundary
  // indicator to the manifold indicators in order for the object to
  // be refined accordingly.
  // We can then refine twice:
  GridTools::copy_boundary_to_manifold_id(triangulation);
  const SphericalManifold<2> boundary_description(Point<2>(0,0));
  triangulation.set_manifold (1, boundary_description);
  triangulation.refine_global(2);

  // The mesh so generated is then passed to the function that generates
  // output. In a final step we remove the boundary object again so that it is
  // no longer in use by the triangulation when it is destroyed (the boundary
  // object is destroyed first in this function since it was declared after
  // the triangulation).
  mesh_info (triangulation, "grid-3.eps");
  triangulation.set_manifold (1);
}

// There is one snag to doing things as shown above: If one moves the nodes on
// the boundary as shown here, one often ends up with cells in the interior
// that are badly distorted since the interior nodes were not moved around. This
// is not that much of a problem in the current case since the mesh did not
// contain any internal nodes when the nodes were moved -- it was the coarse
// mesh and it so happened that all vertices are at the boundary. It's also
// the case that the movement we had here was, compared to the average cell
// size not overly dramatic. Nevertheless, sometimes one does want to move
// vertices by a significant distance, and in that case one needs to move
// internal nodes as well. One way to do that automatically is to call the
// function GridTools::laplace_transform that takes a set of transformed
// vertex coordinates and moves all of the other vertices in such a way that the
// resulting mesh has, in some sense, a small distortion.

// @sect4{grid_4: Demonstrating extrude_triangulation}

// This example takes the initial grid from the previous function and simply extrudes it into the third space dimension:
void grid_4()
{
  Triangulation<2> triangulation;
  Triangulation<3> out;
  GridGenerator::hyper_cube_with_cylindrical_hole (triangulation, 0.25, 1.0);

  GridGenerator::extrude_triangulation (triangulation, 3, 2.0, out);
  mesh_info(out, "grid-4.eps");

}

// @sect4{grid_5: Demonstrating GridTools::transform, part 1}

// This and the next example first create a mesh and then transform it by
// moving every node of the mesh according to a function that takes a point
// and returns a mapped point. In this case, we transform $(x,y) \mapsto
// (x,y+\sin(\pi x/5))$.
//
// GridTools::transform takes a triangulation and any kind of object that can
// be called like a function as arguments. This function-like argument can be
// simply the address of a function as in the current case, or an object that
// has an operator() as in the next example, or for example a
// std::function@<Point@<2@>(const Point@<2@>)@> object one can get
// via std::bind in more complex cases.
Point<2> grid_5_transform (const Point<2> &in)
{
  return Point<2>(in(0),
                  in(1) + std::sin(in(0)/5.0*3.14159));
}

void grid_5()
{
  Triangulation<2> tria;
  std::vector<unsigned int> repetitions(2);
  repetitions[0] = 14;
  repetitions[1] = 2;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(10.0,1.0));

  GridTools::transform(&grid_5_transform, tria);
  mesh_info(tria, "grid-5.eps");
}

// @sect4{grid_6: Demonstrating GridTools::transform, part 2}

// In this second example of transforming points from an original to a new
// mesh, we will use the mapping $(x,y) \mapsto (x,\tanh(2y)/\tanh(2))$. To
// make things more interesting, rather than doing so in a single function as
// in the previous example, we here create an object with an
// operator() that will be called by GridTools::transform. Of
// course, this object may in reality be much more complex: the object may
// have member variables that play a role in computing the new locations of
// vertices.
struct Grid6Func
{
  double trans(const double y) const
  {
    return std::tanh(2*y)/tanh(2);
  }

  Point<2> operator() (const Point<2> &in) const
  {
    return Point<2> (in(0),
                     trans(in(1)));
  }
};

void grid_6()
{
  Triangulation<2> tria;
  std::vector< unsigned int > repetitions(2);
  repetitions[0] = repetitions[1] = 40;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(1.0,1.0));

  GridTools::transform(Grid6Func(), tria);
  mesh_info(tria, "grid-6.eps");
}

// @sect4{grid_7: Demonstrating distort_random}

// In this last example, we create a mesh and then distort its (interior)
// vertices by a random perturbation. This is not something you want to do for
// production computations, but it is a useful tool for testing
// discretizations and codes to make sure they don't work just by accident
// because the mesh happens to be uniformly structured and supporting
// super-convergence properties.
void grid_7()
{
  Triangulation<2> tria;
  std::vector<unsigned int> repetitions(2);
  repetitions[0] = repetitions[1] = 16;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(1.0,1.0));

  GridTools::distort_random (0.3, tria, true);
  mesh_info(tria, "grid-7.eps");
}

// @sect3{The main function}

// Finally, the main function. There isn't much to do here, only to call the
// subfunctions.
int main ()
{
  grid_1 ();
  grid_2 ();
  grid_3 ();
  grid_4 ();
  grid_5 ();
  grid_6 ();
  grid_7 ();
}
<commit_msg>Change mesh_info() to print_mesh_info().<commit_after>/* ---------------------------------------------------------------------
 *
 * Copyright (C) 2013 - 2015 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE at
 * the top level of the deal.II distribution.
 *
 * ---------------------------------------------------------------------

 *
 * Author: Timo Heister, Texas A&M University, 2013
 */

// This tutorial program is odd in the sense that, unlike for most other
// steps, the introduction already provides most of the information on how to
// use the various strategies to generate meshes. Consequently, there is
// little that remains to be commented on here, and we intersperse the code
// with relatively little text. In essence, the code here simply provides a
// reference implementation of what has already been described in the
// introduction.

// @sect3{Include files}

#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_in.h>

#include <iostream>
#include <fstream>

#include <map>

using namespace dealii;

// @sect3{Generating output for a given mesh}

// The following function generates some output for any of the meshes we will
// be generating in the remainder of this program. In particular, it generates
// the following information:
//
// - Some general information about the number of space dimensions in which
//   this mesh lives and its number of cells.
// - The number of boundary faces that use each boundary indicator, so that
//   it can be compared with what we expect.
//
// Finally, the function outputs the mesh in encapsulated postscript (EPS)
// format that can easily be visualized in the same way as was done in step-1.
template <int dim>
void print_mesh_info(const Triangulation<dim> &tria,
                     const std::string        &filename)
{
  std::cout << "Mesh info:" << std::endl
            << " dimension: " << dim << std::endl
            << " no. of cells: " << tria.n_active_cells() << std::endl;

  // Next loop over all faces of all cells and find how often each
  // boundary indicator is used (recall that if you access an element
  // of a std::map object that doesn't exist, it is implicitly created
  // and default initialized -- to zero, in the current case -- before
  // we then increment it):
  {
    std::map<unsigned int, unsigned int> boundary_count;
    typename Triangulation<dim>::active_cell_iterator
    cell = tria.begin_active(),
    endc = tria.end();
    for (; cell!=endc; ++cell)
      {
        for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
          {
            if (cell->face(face)->at_boundary())
              boundary_count[cell->face(face)->boundary_id()]++;
          }
      }

    std::cout << " boundary indicators: ";
    for (std::map<unsigned int, unsigned int>::iterator it=boundary_count.begin();
         it!=boundary_count.end();
         ++it)
      {
        std::cout << it->first << "(" << it->second << " times) ";
      }
    std::cout << std::endl;
  }

  // Finally, produce a graphical representation of the mesh to an output
  // file:
  std::ofstream out (filename.c_str());
  GridOut grid_out;
  grid_out.write_eps (tria, out);
  std::cout << " written to " << filename
            << std::endl
            << std::endl;
}

// @sect3{Main routines}

// @sect4{grid_1: Loading a mesh generated by gmsh}

// In this first example, we show how to load the mesh for which we have
// discussed in the introduction how to generate it. This follows the same
// pattern as used in step-5 to load a mesh, although there it was written in
// a different file format (UCD instead of MSH).
void grid_1 ()
{
  Triangulation<2> triangulation;

  GridIn<2> gridin;
  gridin.attach_triangulation(triangulation);
  std::ifstream f("untitled.msh");
  gridin.read_msh(f);

  print_mesh_info(triangulation, "grid-1.eps");
}

// @sect4{grid_2: Merging triangulations}

// Here, we first create two triangulations and then merge them into one.  As
// discussed in the introduction, it is important to ensure that the vertices
// at the common interface are located at the same coordinates.
void grid_2 ()
{
  Triangulation<2> tria1;
  GridGenerator::hyper_cube_with_cylindrical_hole (tria1, 0.25, 1.0);

  Triangulation<2> tria2;
  std::vector< unsigned int > repetitions(2);
  repetitions[0]=3;
  repetitions[1]=2;
  GridGenerator::subdivided_hyper_rectangle (tria2, repetitions,
                                             Point<2>(1.0,-1.0),
                                             Point<2>(4.0,1.0));

  Triangulation<2> triangulation;
  GridGenerator::merge_triangulations (tria1, tria2, triangulation);

  print_mesh_info(triangulation, "grid-2.eps");
}

// @sect4{grid_3: Moving vertices}

// In this function, we move vertices of a mesh. This is simpler than one
// usually expects: if you ask a cell using cell-@>vertex(i) for
// the coordinates of its ith vertex, it doesn't just provide the
// location of this vertex but in fact a reference to the location where these
// coordinates are stored. We can then modify the value stored there.
//
// So this is what we do in the first part of this function: We create a
// square of geometry $[-1,1]^2$ with a circular hole with radius 0.25 located
// at the origin. We then loop over all cells and all vertices and if a vertex
// has a $y$ coordinate equal to one, we move it upward by 0.5.
//
// Note that this sort of procedure does not usually work this way because one
// will typically encounter the same vertices multiple times and may move them
// more than once. It works here because we select the vertices we want to use
// based on their geometric location, and a vertex moved once will fail this
// test in the future. A more general approach to this problem would have been
// to keep a std::set of of those vertex indices that we have already moved
// (which we can obtain using cell-@>vertex_index(i) and only
// move those vertices whose index isn't in the set yet.
void grid_3 ()
{
  Triangulation<2> triangulation;
  GridGenerator::hyper_cube_with_cylindrical_hole (triangulation, 0.25, 1.0);

  Triangulation<2>::active_cell_iterator
  cell = triangulation.begin_active(),
  endc = triangulation.end();
  for (; cell!=endc; ++cell)
    {
      for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
        {
          Point<2> &v = cell->vertex(i);
          if (std::abs(v(1)-1.0)<1e-5)
            v(1) += 0.5;
        }
    }

  // In the second step we will refine the mesh twice. To do this
  // correctly, we have to associate a geometry object with the
  // boundary of the hole; since the boundary of the hole has boundary
  // indicator 1 (see the documentation of the function that generates
  // the mesh), we need to create an object that describes a spherical
  // manifold (i.e., a hyper ball) with appropriate center and assign
  // it to the triangulation. Notice that the function that generates
  // the triangulation sets the boundary indicators of the inner mesh,
  // but leaves unchanged the manifold indicator. We copy the boundary
  // indicator to the manifold indicators in order for the object to
  // be refined accordingly.
  // We can then refine twice:
  GridTools::copy_boundary_to_manifold_id(triangulation);
  const SphericalManifold<2> boundary_description(Point<2>(0,0));
  triangulation.set_manifold (1, boundary_description);
  triangulation.refine_global(2);

  // The mesh so generated is then passed to the function that generates
  // output. In a final step we remove the boundary object again so that it is
  // no longer in use by the triangulation when it is destroyed (the boundary
  // object is destroyed first in this function since it was declared after
  // the triangulation).
  print_mesh_info (triangulation, "grid-3.eps");
  triangulation.set_manifold (1);
}

// There is one snag to doing things as shown above: If one moves the nodes on
// the boundary as shown here, one often ends up with cells in the interior
// that are badly distorted since the interior nodes were not moved around. This
// is not that much of a problem in the current case since the mesh did not
// contain any internal nodes when the nodes were moved -- it was the coarse
// mesh and it so happened that all vertices are at the boundary. It's also
// the case that the movement we had here was, compared to the average cell
// size not overly dramatic. Nevertheless, sometimes one does want to move
// vertices by a significant distance, and in that case one needs to move
// internal nodes as well. One way to do that automatically is to call the
// function GridTools::laplace_transform that takes a set of transformed
// vertex coordinates and moves all of the other vertices in such a way that the
// resulting mesh has, in some sense, a small distortion.

// @sect4{grid_4: Demonstrating extrude_triangulation}

// This example takes the initial grid from the previous function and simply extrudes it into the third space dimension:
void grid_4()
{
  Triangulation<2> triangulation;
  Triangulation<3> out;
  GridGenerator::hyper_cube_with_cylindrical_hole (triangulation, 0.25, 1.0);

  GridGenerator::extrude_triangulation (triangulation, 3, 2.0, out);
  print_mesh_info(out, "grid-4.eps");
}

// @sect4{grid_5: Demonstrating GridTools::transform, part 1}

// This and the next example first create a mesh and then transform it by
// moving every node of the mesh according to a function that takes a point
// and returns a mapped point. In this case, we transform $(x,y) \mapsto
// (x,y+\sin(\pi x/5))$.
//
// GridTools::transform takes a triangulation and any kind of object that can
// be called like a function as arguments. This function-like argument can be
// simply the address of a function as in the current case, or an object that
// has an operator() as in the next example, or for example a
// std::function@<Point@<2@>(const Point@<2@>)@> object one can get
// via std::bind in more complex cases.
Point<2> grid_5_transform (const Point<2> &in)
{
  return Point<2>(in(0),
                  in(1) + std::sin(in(0)/5.0*3.14159));
}

void grid_5()
{
  Triangulation<2> tria;
  std::vector<unsigned int> repetitions(2);
  repetitions[0] = 14;
  repetitions[1] = 2;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(10.0,1.0));

  GridTools::transform(&grid_5_transform, tria);
  print_mesh_info(tria, "grid-5.eps");
}

// @sect4{grid_6: Demonstrating GridTools::transform, part 2}

// In this second example of transforming points from an original to a new
// mesh, we will use the mapping $(x,y) \mapsto (x,\tanh(2y)/\tanh(2))$. To
// make things more interesting, rather than doing so in a single function as
// in the previous example, we here create an object with an
// operator() that will be called by GridTools::transform. Of
// course, this object may in reality be much more complex: the object may
// have member variables that play a role in computing the new locations of
// vertices.
struct Grid6Func
{
  double trans(const double y) const
  {
    return std::tanh(2*y)/tanh(2);
  }

  Point<2> operator() (const Point<2> &in) const
  {
    return Point<2> (in(0),
                     trans(in(1)));
  }
};

void grid_6()
{
  Triangulation<2> tria;
  std::vector< unsigned int > repetitions(2);
  repetitions[0] = repetitions[1] = 40;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(1.0,1.0));

  GridTools::transform(Grid6Func(), tria);
  print_mesh_info(tria, "grid-6.eps");
}

// @sect4{grid_7: Demonstrating distort_random}

// In this last example, we create a mesh and then distort its (interior)
// vertices by a random perturbation. This is not something you want to do for
// production computations, but it is a useful tool for testing
// discretizations and codes to make sure they don't work just by accident
// because the mesh happens to be uniformly structured and supporting
// super-convergence properties.
void grid_7()
{
  Triangulation<2> tria;
  std::vector<unsigned int> repetitions(2);
  repetitions[0] = repetitions[1] = 16;
  GridGenerator::subdivided_hyper_rectangle (tria, repetitions,
                                             Point<2>(0.0,0.0),
                                             Point<2>(1.0,1.0));

  GridTools::distort_random (0.3, tria, true);
  print_mesh_info(tria, "grid-7.eps");
}

// @sect3{The main function}

// Finally, the main function. There isn't much to do here, only to call the
// subfunctions.
int main ()
{
  grid_1 ();
  grid_2 ();
  grid_3 ();
  grid_4 ();
  grid_5 ();
  grid_6 ();
  grid_7 ();
}
<|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.

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

// Testing
#include "mitkTestFixture.h"
#include "mitkTestingMacros.h"

// qt includes
#include <qapplication>

// std includes
#include <string>

// MITK includes
#include "QmitkChartWidget.h"
#include "QmitkChartxyData.h"
#include "QmitkChartData.h"

class mitkChartWidgetTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkChartWidgetTestSuite);

  // Test the dicom property parsing
  MITK_TEST(AddOnce_Test_Success);
  MITK_TEST(AddSameLabelTwice_Test_Success);
  MITK_TEST(RemoveNonexistingData_Failure);
  MITK_TEST(RemoveData_Success);
  MITK_TEST(SetandGet_Success);
  MITK_TEST(SetC3DataAndGet_Success);
  MITK_TEST(AddAndRemoveData_Sucess);
  // MITK_TEST(AddAndGet)
  CPPUNIT_TEST_SUITE_END();

private:
  std::vector<double> data1D;
  std::string label;

public:
  void setUp() override
  {
    data1D = {2, 4, 7, 8, 21, 5, 12, 65, 41, 9};
    label = "testLabel";

    int argc = 1;
    char *argv[] = {"AppName"};
    if (QApplication::instance() == nullptr)
    {
      new QApplication(argc, argv);
    }
  }

  void tearDown() override {}

  void AddOnce_Test_Success()
  {
    QmitkChartWidget widget;
    CPPUNIT_ASSERT_NO_THROW_MESSAGE("Adding data caused an exception", widget.AddData1D(data1D, label));

    std::vector<std::unique_ptr<QmitkChartxyData>> *dataVector = widget.GetData();

    CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 1 && dataVector != nullptr);
    QmitkChartxyData * dataPtr = dataVector->at(0).get();

    CPPUNIT_ASSERT_MESSAGE("Label differs for no obvious reason", dataPtr->GetLabel().toString().toStdString() == label);

    std::vector<QVariant> insertedYData = dataPtr->GetYData().toVector().toStdVector();
    CPPUNIT_ASSERT_MESSAGE("Data differs in size", insertedYData.size() == data1D.size());

    for (int i = 0; i < data1D.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D[i] == insertedYData[i]);
    }
  }

  void AddSameLabelTwice_Test_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
    widget.AddData1D(data1D, label);

    auto dataVector = widget.GetData();

    QmitkChartxyData* xyData1 = dataVector->at(0).get();
    QmitkChartxyData* xyData2 = dataVector->at(1).get();

    QVariant dataLabel1 = xyData1->GetLabel();
    QVariant dataLabel2 = xyData2->GetLabel();
    CPPUNIT_ASSERT_MESSAGE("The two dataLabel are the same", dataLabel1 != dataLabel2);

    QString string1 = dataLabel1.toString();
    QString string2 = dataLabel2.toString();

    std::string stdString1 = string1.toStdString();
    std::string stdString2 = string2.toStdString();
    CPPUNIT_ASSERT_MESSAGE("The first dataLabel isn't still the same", stdString1 == label);
    CPPUNIT_ASSERT_MESSAGE("The second dataLabel is still the same", stdString2 != label);
  }

  void AddAndRemoveData_Sucess()
  {
    std::vector<double> data1D2 = {2, 2};
    std::string label2 = "testData2";
    std::vector<double> data1D3 = {3, 3, 3};
    std::string label3 = "testData3";
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
	widget.AddData1D(data1D2, label2);
    widget.AddData1D(data1D3, label3);
	auto dataVector = widget.GetData();
    // data with {data1D0, data1D2, data1D3}
	CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 3 && dataVector != nullptr);
	widget.RemoveData(label2);
  // data with {data1D0, data1D3}
	CPPUNIT_ASSERT_MESSAGE("Removing data failed.", dataVector->size() == 2 && dataVector != nullptr);
	    QmitkChartxyData *xyData1 = dataVector->at(0).get();
    std::vector<QVariant> insertedYData = xyData1->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D[i] == insertedYData[i]);
    }
    QmitkChartxyData *xyData2 = dataVector->at(1).get();
    insertedYData = xyData2->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D3.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D3[i] == insertedYData[i]);
    }
    widget.RemoveData(label);
    // data with {data1D3}
    CPPUNIT_ASSERT_MESSAGE("Removing data failed.", dataVector->size() == 1 && dataVector != nullptr);
    widget.AddData1D(data1D2, label2);
    CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 2 && dataVector != nullptr);

	//data with {data1D3, data1D2}
    xyData1 = dataVector->at(0).get();
    insertedYData = xyData1->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D3.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D3[i] == insertedYData[i]);
    }
    xyData2 = dataVector->at(1).get();
    insertedYData = xyData2->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D2.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D2[i] == insertedYData[i]);
    }

  }

  void RemoveNonexistingData_Failure()
  {
    QmitkChartWidget widget;

    CPPUNIT_ASSERT_THROW_MESSAGE(
      "Removin nonexistend label did not throw exception", widget.RemoveData(label), std::invalid_argument);
  }

  void RemoveData_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);

    CPPUNIT_ASSERT_NO_THROW_MESSAGE("Removin nonexistend label did not throw exception", widget.RemoveData(label));
  }

  void SetandGet_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
    std::string colorName = "green";

    auto mitkChartxyData = widget.GetData();
    QmitkChartxyData *xyData1 = mitkChartxyData->at(0).get();

	//set color test
	widget.SetColor(label, colorName);
	auto qVariantColor = xyData1->GetColor();
	QString qStringColor = qVariantColor.toString();
	CPPUNIT_ASSERT_MESSAGE("The color isn't the assigned color", colorName == qStringColor.toStdString());

	//set line style test
    QVariant defaultLineStyle = xyData1->GetLineStyle();

    widget.SetLineStyle(label, QmitkChartWidget::LineStyle::dashed);
	QVariant lineStyle = xyData1->GetLineStyle();

	QVariant defaultChartType = xyData1->GetChartType();
    auto line= std::make_pair("line", QmitkChartWidget::ChartType::line);
  if (defaultChartType.toString().toStdString() != line.first)
	{
		CPPUNIT_ASSERT_MESSAGE("The line style could be changed without ChartType line",
			defaultLineStyle == lineStyle);
	}

	//set ChartType
  widget.SetChartType(label, QmitkChartWidget::ChartType::line);
  QVariant chartType = xyData1->GetChartType();

  CPPUNIT_ASSERT_MESSAGE("The chart type could not be changed to line",
	  chartType.toString().toStdString() == line.first);

  //set line style with chart type line
  widget.SetLineStyle(label, QmitkChartWidget::LineStyle::dashed);
  lineStyle = xyData1->GetLineStyle();
  CPPUNIT_ASSERT_MESSAGE("The line style could not be changed", "dashed" == lineStyle.toString().toStdString());

  }

  void SetC3DataAndGet_Success()
   {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);

	//set YAxisScale
    widget.SetYAxisScale(QmitkChartWidget::AxisScale::log);
    QmitkChartData *c3Data = widget.GetC3Data();
    QVariant yAxisScale = c3Data->GetYAxisScale();
    CPPUNIT_ASSERT_MESSAGE("The YAxisScale could not be changed", "log" == yAxisScale.toString().toStdString());

	//set Title
    std::string testTitle = "testTitle";
    widget.SetTitle(testTitle);
    QVariant title = c3Data->GetTitle();
    CPPUNIT_ASSERT_MESSAGE("The title could not be set", testTitle == title.toString().toStdString());

	//set LegendPosition
    widget.SetLegendPosition(QmitkChartWidget::LegendPosition::right);
    QVariant legendPosition = c3Data->GetLegendPosition();
    CPPUNIT_ASSERT_MESSAGE("The LegendPosition could not be changed", "right" == legendPosition.toString().toStdString());

	//show legend
	QVariant isShowLegend = c3Data->GetShowLegend();
    widget.SetShowLegend(!isShowLegend.toBool());
	QVariant isShowLegendInverted = c3Data->GetShowLegend();
    CPPUNIT_ASSERT_MESSAGE("The ShowLegend could not be changed",
                         isShowLegend.toBool() != isShowLegendInverted.toBool());

	//show dataPoints
	QVariant dataPointSize = c3Data->GetDataPointSize();
    bool showDataPoints = dataPointSize.toInt() > 0;
	widget.SetShowDataPoints(!showDataPoints);
    dataPointSize = c3Data->GetDataPointSize();
	bool showDataPointsInvert = dataPointSize.toInt() > 0;
    CPPUNIT_ASSERT_MESSAGE("The DataPoints could not be changed",
                           isShowLegend.toBool() != isShowLegendInverted.toBool());

	//show SubCharts
    QVariant showSubChart = c3Data->GetShowSubchart();
    widget.Show(!showSubChart.toBool());
    QVariant showSubChartInvert = c3Data->GetShowSubchart();
    CPPUNIT_ASSERT_MESSAGE("The visibility of subCharts could not be changed",
                           showSubChart.toBool() != showSubChartInvert.toBool());
   }
};

MITK_TEST_SUITE_REGISTRATION(mitkChartWidget)<commit_msg>use QApplication instead of qapplication for linux gcc<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.

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

// Testing
#include "mitkTestFixture.h"
#include "mitkTestingMacros.h"

// qt includes
#include "QApplication"
#include <qapplication>

// std includes
#include <string>

// MITK includes
#include "QmitkChartWidget.h"
#include "QmitkChartxyData.h"
#include "QmitkChartData.h"

class mitkChartWidgetTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkChartWidgetTestSuite);

  // Test the dicom property parsing
  MITK_TEST(AddOnce_Test_Success);
  MITK_TEST(AddSameLabelTwice_Test_Success);
  MITK_TEST(RemoveNonexistingData_Failure);
  MITK_TEST(RemoveData_Success);
  MITK_TEST(SetandGet_Success);
  MITK_TEST(SetC3DataAndGet_Success);
  MITK_TEST(AddAndRemoveData_Sucess);
  // MITK_TEST(AddAndGet)
  CPPUNIT_TEST_SUITE_END();

private:
  std::vector<double> data1D;
  std::string label;

public:
  void setUp() override
  {
    data1D = {2, 4, 7, 8, 21, 5, 12, 65, 41, 9};
    label = "testLabel";

    int argc = 1;
    char *argv[] = {"AppName"};
    if (QApplication::instance() == nullptr)
    {
      new QApplication(argc, argv);
    }
  }

  void tearDown() override {}

  void AddOnce_Test_Success()
  {
    QmitkChartWidget widget;
    CPPUNIT_ASSERT_NO_THROW_MESSAGE("Adding data caused an exception", widget.AddData1D(data1D, label));

    std::vector<std::unique_ptr<QmitkChartxyData>> *dataVector = widget.GetData();

    CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 1 && dataVector != nullptr);
    QmitkChartxyData * dataPtr = dataVector->at(0).get();

    CPPUNIT_ASSERT_MESSAGE("Label differs for no obvious reason", dataPtr->GetLabel().toString().toStdString() == label);

    std::vector<QVariant> insertedYData = dataPtr->GetYData().toVector().toStdVector();
    CPPUNIT_ASSERT_MESSAGE("Data differs in size", insertedYData.size() == data1D.size());

    for (int i = 0; i < data1D.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D[i] == insertedYData[i]);
    }
  }

  void AddSameLabelTwice_Test_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
    widget.AddData1D(data1D, label);

    auto dataVector = widget.GetData();

    QmitkChartxyData* xyData1 = dataVector->at(0).get();
    QmitkChartxyData* xyData2 = dataVector->at(1).get();

    QVariant dataLabel1 = xyData1->GetLabel();
    QVariant dataLabel2 = xyData2->GetLabel();
    CPPUNIT_ASSERT_MESSAGE("The two dataLabel are the same", dataLabel1 != dataLabel2);

    QString string1 = dataLabel1.toString();
    QString string2 = dataLabel2.toString();

    std::string stdString1 = string1.toStdString();
    std::string stdString2 = string2.toStdString();
    CPPUNIT_ASSERT_MESSAGE("The first dataLabel isn't still the same", stdString1 == label);
    CPPUNIT_ASSERT_MESSAGE("The second dataLabel is still the same", stdString2 != label);
  }

  void AddAndRemoveData_Sucess()
  {
    std::vector<double> data1D2 = {2, 2};
    std::string label2 = "testData2";
    std::vector<double> data1D3 = {3, 3, 3};
    std::string label3 = "testData3";
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
	widget.AddData1D(data1D2, label2);
    widget.AddData1D(data1D3, label3);
	auto dataVector = widget.GetData();
    // data with {data1D0, data1D2, data1D3}
	CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 3 && dataVector != nullptr);
	widget.RemoveData(label2);
  // data with {data1D0, data1D3}
	CPPUNIT_ASSERT_MESSAGE("Removing data failed.", dataVector->size() == 2 && dataVector != nullptr);
	    QmitkChartxyData *xyData1 = dataVector->at(0).get();
    std::vector<QVariant> insertedYData = xyData1->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D[i] == insertedYData[i]);
    }
    QmitkChartxyData *xyData2 = dataVector->at(1).get();
    insertedYData = xyData2->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D3.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D3[i] == insertedYData[i]);
    }
    widget.RemoveData(label);
    // data with {data1D3}
    CPPUNIT_ASSERT_MESSAGE("Removing data failed.", dataVector->size() == 1 && dataVector != nullptr);
    widget.AddData1D(data1D2, label2);
    CPPUNIT_ASSERT_MESSAGE("Adding data failed.", dataVector->size() == 2 && dataVector != nullptr);

	//data with {data1D3, data1D2}
    xyData1 = dataVector->at(0).get();
    insertedYData = xyData1->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D3.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D3[i] == insertedYData[i]);
    }
    xyData2 = dataVector->at(1).get();
    insertedYData = xyData2->GetYData().toVector().toStdVector();
    for (int i = 0; i < data1D2.size(); ++i)
    {
      CPPUNIT_ASSERT_MESSAGE("The inserted data differs when checked", data1D2[i] == insertedYData[i]);
    }

  }

  void RemoveNonexistingData_Failure()
  {
    QmitkChartWidget widget;

    CPPUNIT_ASSERT_THROW_MESSAGE(
      "Removin nonexistend label did not throw exception", widget.RemoveData(label), std::invalid_argument);
  }

  void RemoveData_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);

    CPPUNIT_ASSERT_NO_THROW_MESSAGE("Removin nonexistend label did not throw exception", widget.RemoveData(label));
  }

  void SetandGet_Success()
  {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);
    std::string colorName = "green";

    auto mitkChartxyData = widget.GetData();
    QmitkChartxyData *xyData1 = mitkChartxyData->at(0).get();

	//set color test
	widget.SetColor(label, colorName);
	auto qVariantColor = xyData1->GetColor();
	QString qStringColor = qVariantColor.toString();
	CPPUNIT_ASSERT_MESSAGE("The color isn't the assigned color", colorName == qStringColor.toStdString());

	//set line style test
    QVariant defaultLineStyle = xyData1->GetLineStyle();

    widget.SetLineStyle(label, QmitkChartWidget::LineStyle::dashed);
	QVariant lineStyle = xyData1->GetLineStyle();

	QVariant defaultChartType = xyData1->GetChartType();
    auto line= std::make_pair("line", QmitkChartWidget::ChartType::line);
  if (defaultChartType.toString().toStdString() != line.first)
	{
		CPPUNIT_ASSERT_MESSAGE("The line style could be changed without ChartType line",
			defaultLineStyle == lineStyle);
	}

	//set ChartType
  widget.SetChartType(label, QmitkChartWidget::ChartType::line);
  QVariant chartType = xyData1->GetChartType();

  CPPUNIT_ASSERT_MESSAGE("The chart type could not be changed to line",
	  chartType.toString().toStdString() == line.first);

  //set line style with chart type line
  widget.SetLineStyle(label, QmitkChartWidget::LineStyle::dashed);
  lineStyle = xyData1->GetLineStyle();
  CPPUNIT_ASSERT_MESSAGE("The line style could not be changed", "dashed" == lineStyle.toString().toStdString());

  }

  void SetC3DataAndGet_Success()
   {
    QmitkChartWidget widget;
    widget.AddData1D(data1D, label);

	//set YAxisScale
    widget.SetYAxisScale(QmitkChartWidget::AxisScale::log);
    QmitkChartData *c3Data = widget.GetC3Data();
    QVariant yAxisScale = c3Data->GetYAxisScale();
    CPPUNIT_ASSERT_MESSAGE("The YAxisScale could not be changed", "log" == yAxisScale.toString().toStdString());

	//set Title
    std::string testTitle = "testTitle";
    widget.SetTitle(testTitle);
    QVariant title = c3Data->GetTitle();
    CPPUNIT_ASSERT_MESSAGE("The title could not be set", testTitle == title.toString().toStdString());

	//set LegendPosition
    widget.SetLegendPosition(QmitkChartWidget::LegendPosition::right);
    QVariant legendPosition = c3Data->GetLegendPosition();
    CPPUNIT_ASSERT_MESSAGE("The LegendPosition could not be changed", "right" == legendPosition.toString().toStdString());

	//show legend
	QVariant isShowLegend = c3Data->GetShowLegend();
    widget.SetShowLegend(!isShowLegend.toBool());
	QVariant isShowLegendInverted = c3Data->GetShowLegend();
    CPPUNIT_ASSERT_MESSAGE("The ShowLegend could not be changed",
                         isShowLegend.toBool() != isShowLegendInverted.toBool());

	//show dataPoints
	QVariant dataPointSize = c3Data->GetDataPointSize();
    bool showDataPoints = dataPointSize.toInt() > 0;
	widget.SetShowDataPoints(!showDataPoints);
    dataPointSize = c3Data->GetDataPointSize();
	bool showDataPointsInvert = dataPointSize.toInt() > 0;
    CPPUNIT_ASSERT_MESSAGE("The DataPoints could not be changed",
                           isShowLegend.toBool() != isShowLegendInverted.toBool());

	//show SubCharts
    QVariant showSubChart = c3Data->GetShowSubchart();
    widget.Show(!showSubChart.toBool());
    QVariant showSubChartInvert = c3Data->GetShowSubchart();
    CPPUNIT_ASSERT_MESSAGE("The visibility of subCharts could not be changed",
                           showSubChart.toBool() != showSubChartInvert.toBool());
   }
};

MITK_TEST_SUITE_REGISTRATION(mitkChartWidget)<|endoftext|>


<commit_before><commit_msg>-1 -> Z_ERRNO for clarity<commit_after><|endoftext|>


<commit_before>#include "QmitkNodeDescriptorManager.h"
#include <memory>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAND.h>
#include <mitkNodePredicateDataType.h>
#include <mitkProperties.h>
#include <QList>

QmitkNodeDescriptorManager* QmitkNodeDescriptorManager::GetInstance()
{
  static QmitkNodeDescriptorManager _Instance;
  return &_Instance;
/*
  static std::auto_ptr<QmitkNodeDescriptorManager> instance;
  if(instance.get() == 0)
  {
    instance.reset(new QmitkNodeDescriptorManager());
    instance->Initialize();
  }
  return instance.get();*/

}

void QmitkNodeDescriptorManager::Initialize()
{
  // Adding "Images"
  mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/Qmitk/data-type-image-24.png"), isImage, this));

  // Adding "Image Masks"
  mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
  mitk::NodePredicateAND::Pointer isBinaryImage = mitk::NodePredicateAND::New(isBinary, isImage);
  this->AddDescriptor(new QmitkNodeDescriptor(tr("ImageMask"), QString(":/Qmitk/data-type-image-mask-24.png"), isBinaryImage, this));

  // Adding "PointSet"
  mitk::NodePredicateDataType::Pointer isPointSet = mitk::NodePredicateDataType::New("PointSet");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PointSet"), QString(":/Qmitk/data-type-pointset-24"), isPointSet, this));

  // Adding "Surface"
  mitk::NodePredicateDataType::Pointer isSurface = mitk::NodePredicateDataType::New("Surface");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("Surface"), QString(":/Qmitk/data-type-mesh-24.png"), isSurface, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarLine = mitk::NodePredicateDataType::New("PlanarLine");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarLine"), QString(":/Qmitk/data-type-line.png"), isPlanarLine, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarCircle = mitk::NodePredicateDataType::New("PlanarCircle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarCircle"), QString(":/Qmitk/data-type-circle.png"), isPlanarCircle, this));

  // Adding "PlanarAngle"
  mitk::NodePredicateDataType::Pointer isPlanarAngle = mitk::NodePredicateDataType::New("PlanarAngle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarAngle"), QString(":/Qmitk/data-type-angle.png"), isPlanarAngle, this));

  // Adding "PlanarFourPointAngle"
  mitk::NodePredicateDataType::Pointer isPlanarFourPointAngle = mitk::NodePredicateDataType::New("PlanarFourPointAngle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarFourPointAngle"), QString(":/Qmitk/data-type-four-point-angle.png"), isPlanarFourPointAngle, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarPolygon = mitk::NodePredicateDataType::New("PlanarPolygon");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarPolygon"), QString(":/Qmitk/data-type-polygon.png"), isPlanarPolygon, this));
}

void QmitkNodeDescriptorManager::AddDescriptor( QmitkNodeDescriptor* _Descriptor )
{
  _Descriptor->setParent(this);
  m_NodeDescriptors.push_back(_Descriptor);
}

void QmitkNodeDescriptorManager::RemoveDescriptor( QmitkNodeDescriptor* _Descriptor )
{
  int index = m_NodeDescriptors.indexOf(_Descriptor);

  if(index != -1)
  {
    m_NodeDescriptors.removeAt(index);
    _Descriptor->setParent(0);
    delete _Descriptor;
  }

}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const mitk::DataTreeNode* _Node ) const
{
  QmitkNodeDescriptor* _Descriptor = m_UnknownDataTreeNodeDescriptor;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->CheckNode(_Node))
      _Descriptor = *it;
  }

  return _Descriptor;
}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const QString& _ClassName ) const
{
  QmitkNodeDescriptor* _Descriptor = 0;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->GetClassName() == _ClassName)
      _Descriptor = *it;
  }

  return _Descriptor;
}
QList<QAction*> QmitkNodeDescriptorManager::GetActions( const mitk::DataTreeNode* _Node ) const
{
  QList<QAction*> actions = m_UnknownDataTreeNodeDescriptor->GetBatchActions();
  actions.append(m_UnknownDataTreeNodeDescriptor->GetActions());
  QmitkNodeDescriptor* lastDescriptor = m_UnknownDataTreeNodeDescriptor;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->CheckNode(_Node))
    {
      actions.append(lastDescriptor->GetSeparator());
      lastDescriptor = *it;
      actions.append(lastDescriptor->GetBatchActions());
      actions.append(lastDescriptor->GetActions());
    }
  }

  return actions;
}

QList<QAction*> QmitkNodeDescriptorManager::GetActions( const std::vector<mitk::DataTreeNode*>& _Nodes ) const
{
  QList<QAction*> actions = m_UnknownDataTreeNodeDescriptor->GetBatchActions();
  std::vector<QmitkNodeDescriptor*> nodeDescriptors;
  QmitkNodeDescriptor* lastDescriptor;

  // find all descriptors for the nodes (unique)
  for( std::vector<mitk::DataTreeNode*>::const_iterator it = _Nodes.begin()
    ; it != _Nodes.end(); ++it)
  {
    lastDescriptor = this->GetDescriptor(*it);
    if(std::find(nodeDescriptors.begin(), nodeDescriptors.end(), lastDescriptor) == nodeDescriptors.end())
      nodeDescriptors.push_back(lastDescriptor);
  }
  // add all actions for the found descriptors
  lastDescriptor = m_UnknownDataTreeNodeDescriptor;
  for( std::vector<QmitkNodeDescriptor*>::const_iterator it = nodeDescriptors.begin()
    ; it != nodeDescriptors.end(); ++it)
  {
    actions.append(lastDescriptor->GetSeparator());
    lastDescriptor = *it;
    actions.append(lastDescriptor->GetBatchActions());
  }

  return actions;
}

QmitkNodeDescriptorManager::QmitkNodeDescriptorManager()
: m_UnknownDataTreeNodeDescriptor(new QmitkNodeDescriptor("Unknown", QString(":/Qmitk/data-type-unknown-24.png"), 0, this))
{
  this->Initialize();
}

QmitkNodeDescriptorManager::~QmitkNodeDescriptorManager()
{
  //delete m_UnknownDataTreeNodeDescriptor;
  //qDeleteAll(m_NodeDescriptors);
}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetUnknownDataTreeNodeDescriptor() const
{
  return m_UnknownDataTreeNodeDescriptor;
}
<commit_msg>FIX (#1895): Added Node Descriptor for PlanarRectangle<commit_after>#include "QmitkNodeDescriptorManager.h"
#include <memory>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAND.h>
#include <mitkNodePredicateDataType.h>
#include <mitkProperties.h>
#include <QList>

QmitkNodeDescriptorManager* QmitkNodeDescriptorManager::GetInstance()
{
  static QmitkNodeDescriptorManager _Instance;
  return &_Instance;
/*
  static std::auto_ptr<QmitkNodeDescriptorManager> instance;
  if(instance.get() == 0)
  {
    instance.reset(new QmitkNodeDescriptorManager());
    instance->Initialize();
  }
  return instance.get();*/

}

void QmitkNodeDescriptorManager::Initialize()
{
  // Adding "Images"
  mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/Qmitk/data-type-image-24.png"), isImage, this));

  // Adding "Image Masks"
  mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
  mitk::NodePredicateAND::Pointer isBinaryImage = mitk::NodePredicateAND::New(isBinary, isImage);
  this->AddDescriptor(new QmitkNodeDescriptor(tr("ImageMask"), QString(":/Qmitk/data-type-image-mask-24.png"), isBinaryImage, this));

  // Adding "PointSet"
  mitk::NodePredicateDataType::Pointer isPointSet = mitk::NodePredicateDataType::New("PointSet");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PointSet"), QString(":/Qmitk/data-type-pointset-24"), isPointSet, this));

  // Adding "Surface"
  mitk::NodePredicateDataType::Pointer isSurface = mitk::NodePredicateDataType::New("Surface");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("Surface"), QString(":/Qmitk/data-type-mesh-24.png"), isSurface, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarLine = mitk::NodePredicateDataType::New("PlanarLine");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarLine"), QString(":/Qmitk/data-type-line.png"), isPlanarLine, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarCircle = mitk::NodePredicateDataType::New("PlanarCircle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarCircle"), QString(":/Qmitk/data-type-circle.png"), isPlanarCircle, this));

  // Adding "PlanarAngle"
  mitk::NodePredicateDataType::Pointer isPlanarAngle = mitk::NodePredicateDataType::New("PlanarAngle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarAngle"), QString(":/Qmitk/data-type-angle.png"), isPlanarAngle, this));

  // Adding "PlanarFourPointAngle"
  mitk::NodePredicateDataType::Pointer isPlanarFourPointAngle = mitk::NodePredicateDataType::New("PlanarFourPointAngle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarFourPointAngle"), QString(":/Qmitk/data-type-four-point-angle.png"), isPlanarFourPointAngle, this));

  // Adding "PlanarRectangle"
  mitk::NodePredicateDataType::Pointer isPlanarRectangle = mitk::NodePredicateDataType::New("PlanarRectangle");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarRectangle"), QString(":/Qmitk/data-type-rectangle.png"), isPlanarRectangle, this));

  // Adding "PlanarLine"
  mitk::NodePredicateDataType::Pointer isPlanarPolygon = mitk::NodePredicateDataType::New("PlanarPolygon");
  this->AddDescriptor(new QmitkNodeDescriptor(tr("PlanarPolygon"), QString(":/Qmitk/data-type-polygon.png"), isPlanarPolygon, this));
}

void QmitkNodeDescriptorManager::AddDescriptor( QmitkNodeDescriptor* _Descriptor )
{
  _Descriptor->setParent(this);
  m_NodeDescriptors.push_back(_Descriptor);
}

void QmitkNodeDescriptorManager::RemoveDescriptor( QmitkNodeDescriptor* _Descriptor )
{
  int index = m_NodeDescriptors.indexOf(_Descriptor);

  if(index != -1)
  {
    m_NodeDescriptors.removeAt(index);
    _Descriptor->setParent(0);
    delete _Descriptor;
  }

}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const mitk::DataTreeNode* _Node ) const
{
  QmitkNodeDescriptor* _Descriptor = m_UnknownDataTreeNodeDescriptor;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->CheckNode(_Node))
      _Descriptor = *it;
  }

  return _Descriptor;
}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const QString& _ClassName ) const
{
  QmitkNodeDescriptor* _Descriptor = 0;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->GetClassName() == _ClassName)
      _Descriptor = *it;
  }

  return _Descriptor;
}
QList<QAction*> QmitkNodeDescriptorManager::GetActions( const mitk::DataTreeNode* _Node ) const
{
  QList<QAction*> actions = m_UnknownDataTreeNodeDescriptor->GetBatchActions();
  actions.append(m_UnknownDataTreeNodeDescriptor->GetActions());
  QmitkNodeDescriptor* lastDescriptor = m_UnknownDataTreeNodeDescriptor;

  for(QList<QmitkNodeDescriptor*>::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
  {
    if((*it)->CheckNode(_Node))
    {
      actions.append(lastDescriptor->GetSeparator());
      lastDescriptor = *it;
      actions.append(lastDescriptor->GetBatchActions());
      actions.append(lastDescriptor->GetActions());
    }
  }

  return actions;
}

QList<QAction*> QmitkNodeDescriptorManager::GetActions( const std::vector<mitk::DataTreeNode*>& _Nodes ) const
{
  QList<QAction*> actions = m_UnknownDataTreeNodeDescriptor->GetBatchActions();
  std::vector<QmitkNodeDescriptor*> nodeDescriptors;
  QmitkNodeDescriptor* lastDescriptor;

  // find all descriptors for the nodes (unique)
  for( std::vector<mitk::DataTreeNode*>::const_iterator it = _Nodes.begin()
    ; it != _Nodes.end(); ++it)
  {
    lastDescriptor = this->GetDescriptor(*it);
    if(std::find(nodeDescriptors.begin(), nodeDescriptors.end(), lastDescriptor) == nodeDescriptors.end())
      nodeDescriptors.push_back(lastDescriptor);
  }
  // add all actions for the found descriptors
  lastDescriptor = m_UnknownDataTreeNodeDescriptor;
  for( std::vector<QmitkNodeDescriptor*>::const_iterator it = nodeDescriptors.begin()
    ; it != nodeDescriptors.end(); ++it)
  {
    actions.append(lastDescriptor->GetSeparator());
    lastDescriptor = *it;
    actions.append(lastDescriptor->GetBatchActions());
  }

  return actions;
}

QmitkNodeDescriptorManager::QmitkNodeDescriptorManager()
: m_UnknownDataTreeNodeDescriptor(new QmitkNodeDescriptor("Unknown", QString(":/Qmitk/data-type-unknown-24.png"), 0, this))
{
  this->Initialize();
}

QmitkNodeDescriptorManager::~QmitkNodeDescriptorManager()
{
  //delete m_UnknownDataTreeNodeDescriptor;
  //qDeleteAll(m_NodeDescriptors);
}

QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetUnknownDataTreeNodeDescriptor() const
{
  return m_UnknownDataTreeNodeDescriptor;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Math_Angle_inl_
#define _Stroika_Foundation_Math_Angle_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Debug/Assertions.h"
#include    "Common.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Math {

            /*
             ********************************************************************************
             *********************************** Math::Angle ********************************
             ********************************************************************************
             */
            inline
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            Angle::Angle ()
                : fAngleInRadians_ { 0 } {
            }
            inline
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            Angle::Angle (double angle, AngleFormat angleFormat)
                : fAngleInRadians_ {
                (angleFormat == AngleFormat::eRadians)
                ? angle
                : (
                    (angleFormat == AngleFormat::eDegrees)
                    ? (angle *  (2 * kPi) / 360.0)
                    : (
                        angle * (2 * kPi) / 400.0
                    )
                )
            } {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                Require (AngleFormat::eSTART <= angle and angle < AngleFormat::eEND);
#endif
            }
            inline  constexpr   double  Angle::AsRadians () const
            {
                return fAngleInRadians_;
            }
            inline  constexpr   double  Angle::AsDegrees () const
            {
                return fAngleInRadians_ * 360.0 / (2 * kPi);
            }
            inline  constexpr   double  Angle::AsGradians () const
            {
                return fAngleInRadians_ * 400.0 / (2 * kPi);
            }
            inline  Angle   Angle::operator+ (const Angle& rhs) const
            {
                return Angle (AsRadians () + rhs.AsRadians ());
            }
            inline  Angle   Angle::operator- (const Angle& rhs) const
            {
                return Angle (AsRadians () - rhs.AsRadians ());
            }
            inline  Angle   Angle::operator* (double rhs) const
            {
                return Angle (AsRadians () * rhs);
            }
            inline  Angle   Angle::operator/ (double rhs) const
            {
                return Angle (AsRadians () / rhs);
            }
            inline  bool    Angle::operator== (const Angle& rhs) const
            {
                return AsRadians () == rhs.AsRadians ();
            }
            inline  bool    Angle::operator!= (const Angle& rhs) const
            {
                return AsRadians () != rhs.AsRadians ();
            }
            inline  bool    Angle::operator< (const Angle& rhs) const
            {
                return AsRadians () < rhs.AsRadians ();
            }
            inline  bool    Angle::operator<= (const Angle& rhs) const
            {
                return AsRadians () <= rhs.AsRadians ();
            }
            inline  bool    Angle::operator> (const Angle& rhs) const
            {
                return AsRadians () > rhs.AsRadians ();
            }
            inline  bool    Angle::operator>= (const Angle& rhs) const
            {
                return AsRadians () >= rhs.AsRadians ();
            }
            inline  const   Angle&  Angle::operator+= (const Angle& rhs)
            {
                fAngleInRadians_ += rhs.AsRadians ();
                return *this;
            }
            inline  const   Angle&  Angle::operator-= (const Angle& rhs)
            {
                fAngleInRadians_ -= rhs.AsRadians ();
                return *this;
            }
            inline  const   Angle&  Angle::operator*= (double rhs)
            {
                fAngleInRadians_ *= rhs;
                return *this;
            }
            inline  const   Angle&  Angle::operator/= (double rhs)
            {
                fAngleInRadians_ /= rhs;
                return *this;
            }

            /*
             ********************************************************************************
             ***************************** Math::operator* **********************************
             ********************************************************************************
             */
            inline  Angle   operator* (double lhs, const Angle& rhs)
            {
                return Angle (lhs * rhs.AsRadians ());
            }

            /*
             ********************************************************************************
             *********************************** Math::Min **********************************
             ********************************************************************************
             */
            inline  Angle   Min (const Angle& a1, const Angle& a2)
            {
                return (a1 < a2) ? a1 : a2;
            }

            /*
             ********************************************************************************
             *********************************** Math::Max **********************************
             ********************************************************************************
             */
            inline  Angle   Max (const Angle& a1, const Angle& a2)
            {
                return (a1 > a2) ? a1 : a2;
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Math_Angle_inl_*/
<commit_msg>tweaked Requires on Math::Angle<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Math_Angle_inl_
#define _Stroika_Foundation_Math_Angle_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Configuration/Enumeration.h"
#include    "../Debug/Assertions.h"
#include    "Common.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Math {

            /*
             ********************************************************************************
             *********************************** Math::Angle ********************************
             ********************************************************************************
             */
            inline
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            Angle::Angle ()
                : fAngleInRadians_ { 0 } {
            }
            inline
#if     !qCompilerAndStdLib_constexpr_Buggy
            constexpr
#endif
            Angle::Angle (double angle, AngleFormat angleFormat)
                : fAngleInRadians_ {
                (angleFormat == AngleFormat::eRadians)
                ? angle
                : (
                    (angleFormat == AngleFormat::eDegrees)
                    ? (angle *  (2 * kPi) / 360.0)
                    : (
                        angle * (2 * kPi) / 400.0
                    )
                )
            } {
#if     qCompilerAndStdLib_constexpr_functions_cpp14Constaints_Buggy
                using   namespace   Configuration;
                Require (ToInt (AngleFormat::eSTART) <= ToInt (angle) and ToInt (angle) < ToInt (AngleFormat::eEND));
#endif
            }
            inline  constexpr   double  Angle::AsRadians () const
            {
                return fAngleInRadians_;
            }
            inline  constexpr   double  Angle::AsDegrees () const
            {
                return fAngleInRadians_ * 360.0 / (2 * kPi);
            }
            inline  constexpr   double  Angle::AsGradians () const
            {
                return fAngleInRadians_ * 400.0 / (2 * kPi);
            }
            inline  Angle   Angle::operator+ (const Angle& rhs) const
            {
                return Angle (AsRadians () + rhs.AsRadians ());
            }
            inline  Angle   Angle::operator- (const Angle& rhs) const
            {
                return Angle (AsRadians () - rhs.AsRadians ());
            }
            inline  Angle   Angle::operator* (double rhs) const
            {
                return Angle (AsRadians () * rhs);
            }
            inline  Angle   Angle::operator/ (double rhs) const
            {
                return Angle (AsRadians () / rhs);
            }
            inline  bool    Angle::operator== (const Angle& rhs) const
            {
                return AsRadians () == rhs.AsRadians ();
            }
            inline  bool    Angle::operator!= (const Angle& rhs) const
            {
                return AsRadians () != rhs.AsRadians ();
            }
            inline  bool    Angle::operator< (const Angle& rhs) const
            {
                return AsRadians () < rhs.AsRadians ();
            }
            inline  bool    Angle::operator<= (const Angle& rhs) const
            {
                return AsRadians () <= rhs.AsRadians ();
            }
            inline  bool    Angle::operator> (const Angle& rhs) const
            {
                return AsRadians () > rhs.AsRadians ();
            }
            inline  bool    Angle::operator>= (const Angle& rhs) const
            {
                return AsRadians () >= rhs.AsRadians ();
            }
            inline  const   Angle&  Angle::operator+= (const Angle& rhs)
            {
                fAngleInRadians_ += rhs.AsRadians ();
                return *this;
            }
            inline  const   Angle&  Angle::operator-= (const Angle& rhs)
            {
                fAngleInRadians_ -= rhs.AsRadians ();
                return *this;
            }
            inline  const   Angle&  Angle::operator*= (double rhs)
            {
                fAngleInRadians_ *= rhs;
                return *this;
            }
            inline  const   Angle&  Angle::operator/= (double rhs)
            {
                fAngleInRadians_ /= rhs;
                return *this;
            }

            /*
             ********************************************************************************
             ***************************** Math::operator* **********************************
             ********************************************************************************
             */
            inline  Angle   operator* (double lhs, const Angle& rhs)
            {
                return Angle (lhs * rhs.AsRadians ());
            }

            /*
             ********************************************************************************
             *********************************** Math::Min **********************************
             ********************************************************************************
             */
            inline  Angle   Min (const Angle& a1, const Angle& a2)
            {
                return (a1 < a2) ? a1 : a2;
            }

            /*
             ********************************************************************************
             *********************************** Math::Max **********************************
             ********************************************************************************
             */
            inline  Angle   Max (const Angle& a1, const Angle& a2)
            {
                return (a1 > a2) ? a1 : a2;
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Math_Angle_inl_*/
<|endoftext|>