text: /******************************************************************************
  *       SOFA, Simulation Open-Framework Architecture, development version     *
  *                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
  *                                                                             *
  * This program is free software; you can 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.                                             *
  *                                                                             *
  * This program is distributed in the hope that it will be useful, but WITHOUT *
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
  * for more details.                                                           *
  *                                                                             *
  * You should have received a copy of the GNU Lesser General Public License    *
  * along with this program. If not, see <http://www.gnu.org/licenses/>.        *
  *******************************************************************************
  * Authors: The SOFA Team and external contributors (see Authors.txt)          *
  *                                                                             *
  * Contact information: contact@sofa-framework.org                             *
  ******************************************************************************/
  #ifndef SOFA_BaseGaussPointSAMPLER_H
  #define SOFA_BaseGaussPointSAMPLER_H
  
  #include <Flexible/config.h>
  #include <sofa/core/DataEngine.h>
  #include <sofa/core/objectmodel/BaseObject.h>
  #include <sofa/defaulttype/Vec.h>
  #include <sofa/helper/vector.h>
  #include <sofa/core/visual/VisualParams.h>
  #include <sofa/helper/OptionsGroup.h>
  
  #define GAUSSLEGENDRE 0
  #define NEWTONCOTES 1
  #define ELASTON 2
  
  
  namespace sofa
  {
  namespace component
  {
  namespace engine
  {
  
  ///Abstract class for sampling integration points according to a specific quadrature method.
  /**
   * Samplers provide:
   * - Sample positions according to integration method of order 'order'
   * - Initial value of deformation gradient according to underlying geometry (eg. surface mesh) and/or user input (to set anisotopy and residual deformation)
   * - Weighted volume associated to each sample (for elastons, this is a vector of volume moments)
   * - sample region (can be used in shape function component to provide an averaged version of the shape function)
   */
  
  
  class SOFA_Flexible_API BaseGaussPointSampler : public core::DataEngine
  {
  public:
      typedef core::DataEngine Inherited;
      SOFA_ABSTRACT_CLASS(BaseGaussPointSampler,Inherited);
  
      typedef SReal Real;
  
      /** @name quadrature method */
      //@{
      Data<helper::OptionsGroup> f_method;    ///< Quadrature method <br>
      /**< \arg \c 0 Gauss-Legendre http://en.wikipedia.org/wiki/Gaussian_quadrature
                                                   \arg \c 1 Newton-Cotes http://en.wikipedia.org/wiki/Newton%E2%80%93Cotes_formulas
                                                   \arg \c 2 Elaston [Martin-2010] http://graphics.ethz.ch/publications/papers/paperMar10.php
                                              */
      //@}
  
      /** @name position data */
      //@{
      static const unsigned int spatial_dimensions = 3;
      typedef defaulttype::Vec<spatial_dimensions,Real> Coord;   // TODO: put as a template to handle the 2D case (currently the conversion 3D-> 2D is done in the deformation mapping) ?
      typedef helper::vector<Coord> SeqPositions;
      typedef helper::ReadAccessor<Data< SeqPositions > > raPositions;
      typedef helper::WriteOnlyAccessor<Data< SeqPositions > > waPositions;
      Data< SeqPositions > f_position; ///< Samples position
      //@}
  
      /** @name orientation data */
      //@{
      typedef defaulttype::Mat<spatial_dimensions,spatial_dimensions,Real> Transform;
      typedef helper::vector<Transform> VTransform;
      Data< VTransform > f_transforms;        ///< linear transformation in world space to orient samples
      //@}
  
  
      /** @name volume integral data */
      //@{
      Data< unsigned int > f_order; ///< Order of quadrature method
      typedef helper::vector<Real> volumeIntegralType;
      Data< helper::vector<volumeIntegralType> > f_volume; ///< Weighted volumes associated to samples
      typedef helper::WriteOnlyAccessor< Data< helper::vector<volumeIntegralType> > > waVolume;
      //@}
  
      /** @name visu data */
      //@{
      Data< float > showSamplesScale; ///< Samples scale
      Data< int > drawMode; ///< Drawing mode: 0. Green points; 1. Green spheres
      Data< float > showIndicesScale; ///< Indices samples scale
      //@}
  
      virtual std::string getTemplateName() const    { return templateName(this);    }
      static std::string templateName(const BaseGaussPointSampler* = NULL) { return std::string();    }
  
      BaseGaussPointSampler()    :   Inherited()
        , f_method ( initData ( &f_method,"method","quadrature method" ) )
        , f_position(initData(&f_position,SeqPositions(),"position","output sample positions"))
        , f_transforms(initData(&f_transforms,VTransform(),"transforms","output sample orientations"))
        , f_order(initData(&f_order,(unsigned int)1,"order","order of quadrature method"))
        , f_volume(initData(&f_volume,helper::vector<volumeIntegralType>(),"volume","output weighted volume"))
        , showSamplesScale(initData(&showSamplesScale,0.0f,"showSamplesScale","show samples scale"))
        , drawMode(initData(&drawMode,0,"drawMode","0: Green points; 1: Green spheres"))
        , showIndicesScale(initData(&showIndicesScale,0.0f,"showIndicesScale", "show indices scale"))
      {
          helper::OptionsGroup methodOptions(3,"0 - Gauss-Legendre"
                                             ,"1 - Newton-Cotes"
                                             ,"2 - Elastons"
                                             );
          methodOptions.setSelectedItem(GAUSSLEGENDRE);
          f_method.setValue(methodOptions);
      }
  
      virtual void init()
      {
          addInput(&f_method);
          addInput(&f_order);
  //        addInput(&f_position); // can be either input or output depending on the sampler
          addOutput(&f_volume);
          addOutput(&f_transforms);
      }
  
      ///@brief Get the number of samples
      unsigned int getNbSamples() {return this->f_position.getValue().size(); }
      ///@brief Get all samples as a const reference
      const SeqPositions& getSamples(){return this->f_position.getValue();}
      ///@brief Get all orientations as a const reference
      const VTransform& getTransforms(){return this->f_transforms.getValue();}
  
  protected:
  
      virtual void draw(const core::visual::VisualParams* vparams)
      {
          if (!vparams->displayFlags().getShowVisualModels()) return;
  
          vparams->drawTool()->saveLastState();
  
          if (showSamplesScale.getValue()>0) {
              switch( drawMode.getValue() ) {
              case 1:
                  vparams->drawTool()->setLightingEnabled(true);
                  vparams->drawTool()->drawSpheres(this->f_position.getValue(),showSamplesScale.getValue(),defaulttype::Vec<4,float>(0.1f, 0.7f, 0.1f, 1.0f));
                  break;
              default:
                  vparams->drawTool()->drawPoints(this->f_position.getValue(),showSamplesScale.getValue(),defaulttype::Vec<4,float>(0.2f, 1.0f, 0.2f, 1.0f));
                  break;
              }
          }
          if (showIndicesScale.getValue()>0) {
              vparams->drawTool()->draw3DText_Indices(this->f_position.getValue(), showIndicesScale.getValue(), defaulttype::Vec<4,float>(0.1f, 0.7f, 0.1f, 1.0f));
          }
  
          vparams->drawTool()->restoreLastState();
      }
  
  
  };
  
  }
  }
  }
  
  #endif
  