<commit_before>/*
OFX RGBLut plugin, a plugin that illustrates the use of the OFX Support library.

Copyright (C) 2013 INRIA
Author Frederic Devernay frederic.devernay@inria.fr

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

  Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

  Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

  Neither the name of the {organization} nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef _WINDOWS
#include <windows.h>
#endif

#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

#include <stdio.h>
#include "ofxsImageEffect.h"
#include "ofxsMultiThread.h"

#include "ofxsProcessing.H"

class RGBLutBase : public OFX::ImageProcessor {
protected :
  OFX::Image *_srcImg;
public :
  RGBLutBase(OFX::ImageEffect &instance): OFX::ImageProcessor(instance), _srcImg(0)
  {
  }
  void setSrcImg(OFX::Image *v) {_srcImg = v;}
};

// template to do the RGBA processing for discrete types
template <class PIX, int nComponents, int nValues>
class ImageRGBLutProcessor : public RGBLutBase
{
protected:
    PIX _lookupTable[3][nValues];
public :
  // ctor
  ImageRGBLutProcessor(OFX::ImageEffect &instance, const OFX::RenderArguments &args)
    : RGBLutBase(instance)
  {
    // build the LUT
    OFX::ParametricParam  *lookupTable = instance.fetchParametricParam("lookupTable");
    assert(lookupTable);
    for(int component = 0; component < 3; ++component) {
      for(PIX position = 0; position < nValues; ++position) {
        // position to evaluate the param at
        float parametricPos = float(position)/(nValues-1);

        // evaluate the parametric param
        double value = lookupTable->getValue(component, args.time, parametricPos);

        // set that in the lut
        _lookupTable[component][position] = std::max(PIX(0),std::min(PIX(value*(nValues-1)+0.5), PIX(nValues-1)));
      }
    }
  }
  // and do some processing
  void multiThreadProcessImages(OfxRectI procWindow)
  {
    assert(_dstImg);
    for(int y = procWindow.y1; y < procWindow.y2; y++)
    {
      if(_effect.abort())
        break;
      PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
      for(int x = procWindow.x1; x < procWindow.x2; x++)
      {
        PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
        if(srcPix)
        {
          for(int c = 0; c < nComponents; c++) {
            assert(0 <= srcPix[c] && srcPix[c] < nValues);
            dstPix[c] = _lookupTable[c][srcPix[c]];
          }
        }
        else
        {
          // no src pixel here, be black and transparent
          for(int c = 0; c < nComponents; c++)
            dstPix[c] = 0;
        }
        // increment the dst pixel
        dstPix += nComponents;
      }
    }
  }
};

// template to do the RGBA processing for floating-point types
template <int nComponents, int nValues>
class ImageRGBLutProcessorFloat : public RGBLutBase
{
protected:
    typedef float PIX;
    PIX _lookupTable[3][nValues];
public :
  // ctor
  ImageRGBLutProcessorFloat(OFX::ImageEffect &instance, const OFX::RenderArguments &args)
    : RGBLutBase(instance)
  {
    // build the LUT
    OFX::ParametricParam  *lookupTable = instance.fetchParametricParam("lookupTable");
    for(int component = 0; component < 3; ++component) {
      for(int position = 0; position < nValues; ++position) {
        // position to evaluate the param at
        double parametricPos = float(position)/(nValues-1);

        // evaluate the parametric param
        double value = lookupTable->getValue(component, args.time, parametricPos);
        //value = value * (nValues-1);
        //value = clamp(value, 0, nValues-1);

        // set that in the lut
        _lookupTable[component][position] = std::max(PIX(0),std::min(PIX(value),PIX(nValues-1)));
      }
    }
  }
  // and do some processing
  void multiThreadProcessImages(OfxRectI procWindow)
  {
    assert(_dstImg);
    for(int y = procWindow.y1; y < procWindow.y2; y++)
    {
      if(_effect.abort())
        break;
      PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
      for(int x = procWindow.x1; x < procWindow.x2; x++)
      {
        PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
        if(srcPix)
        {
          for(int c = 0; c < nComponents; c++) {
            dstPix[c] = interpolate(c, srcPix[c]);
          }
        }
        else
        {
          // no src pixel here, be black and transparent
          for(int c = 0; c < nComponents; c++)
            dstPix[c] = 0;
        }
        // increment the dst pixel
        dstPix += nComponents;
      }
    }
  }
private:
  float interpolate(int component, float value) {
    if (component == 3) { // alpha
      return value;
    }
    if (value < 0.) {
      return _lookupTable[component][0];
    } else if (value >= 1.) {
      return _lookupTable[component][nValues-1];
    } else {
      int i = (int)(value * (nValues-1));
      assert(i < nValues-1);
      float alpha = value - (float)i / (nValues-1);
      return _lookupTable[component][i] * (1.-alpha) + _lookupTable[component][i] * alpha;
    }
  }
};

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class RGBLutPlugin : public OFX::ImageEffect
{
protected :
  OFX::Clip *dstClip_;
  OFX::Clip *srcClip_;

public :
  RGBLutPlugin(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , dstClip_(0)
    , srcClip_(0)
  {
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
  }

  virtual void render(const OFX::RenderArguments &args);
  void setupAndProcess(RGBLutBase &, const OFX::RenderArguments &args);
};

void RGBLutPlugin::setupAndProcess(RGBLutBase &processor, const OFX::RenderArguments &args)
{
  assert(dstClip_);
  std::auto_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
  assert(srcClip_);
  std::auto_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));

  if(src.get() && dst.get())
  {
    OFX::BitDepthEnum    srcBitDepth      = src->getPixelDepth();
    OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
    OFX::BitDepthEnum dstBitDepth       = dst->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dst->getPixelComponents();

    // see if they have the same depths and bytes and all
    if(srcBitDepth != dstBitDepth || srcComponents != dstComponents)
      throw int(1); // HACK!! need to throw an sensible exception here!
  }

  processor.setDstImg(dst.get());
  processor.setSrcImg(src.get());
  processor.setRenderWindow(args.renderWindow);
  processor.process();
}

void RGBLutPlugin::render(const OFX::RenderArguments &args)
{
  assert(dstClip_);
  OFX::BitDepthEnum       dstBitDepth    = dstClip_->getPixelDepth();
  OFX::PixelComponentEnum dstComponents  = dstClip_->getPixelComponents();

  if(dstComponents == OFX::ePixelComponentRGBA)
  {
    switch(dstBitDepth)
    {
    case OFX::eBitDepthUByte :
      {
        ImageRGBLutProcessor<unsigned char, 4, 256> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthUShort :
      {
        ImageRGBLutProcessor<unsigned short, 4, 65536> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthFloat :
      {
        ImageRGBLutProcessorFloat<4,1000> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;
    }
  }
  else {
    switch(dstBitDepth)
    {
    case OFX::eBitDepthUByte :
      {
        ImageRGBLutProcessor<unsigned char, 1, 256> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthUShort :
      {
        ImageRGBLutProcessor<unsigned short, 1, 65536> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthFloat :
      {
        ImageRGBLutProcessorFloat<1,1000> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;
    }
  }
}

mDeclarePluginFactory(RGBLutPluginFactory, {}, {});

using namespace OFX;
void RGBLutPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
  desc.setLabels("RGBLut", "RGBLut", "RGBLut");
  desc.setPluginGrouping("OFX");
  desc.addSupportedContext(eContextFilter);
  desc.addSupportedBitDepth(eBitDepthUByte);
  desc.addSupportedBitDepth(eBitDepthUShort);
  desc.addSupportedBitDepth(eBitDepthFloat);

  desc.setSingleInstance(false);
  desc.setHostFrameThreading(false);
  desc.setSupportsMultiResolution(true);
  desc.setSupportsTiles(true);
  desc.setTemporalClipAccess(false);
  desc.setRenderTwiceAlways(false);
  desc.setSupportsMultipleClipPARs(false);

  if (!OFX::getImageEffectHostDescription()->supportsParametricParameter) {
	throwHostMissingSuiteException(kOfxParametricParameterSuite);
  }
}

void RGBLutPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context)
{
  ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
  assert(srcClip);
  srcClip->addSupportedComponent(ePixelComponentRGBA);
  srcClip->addSupportedComponent(ePixelComponentAlpha);
  srcClip->setTemporalClipAccess(false);
  srcClip->setSupportsTiles(true);
  srcClip->setIsMask(false);

  ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
  assert(dstClip);
  dstClip->addSupportedComponent(ePixelComponentRGBA);
  dstClip->addSupportedComponent(ePixelComponentAlpha);
  dstClip->setSupportsTiles(true);

  if (OFX::getImageEffectHostDescription()->supportsParametricParameter) {
    // define it
    OFX::ParametricParamDescriptor* lookupTable = desc.defineParametricParam("lookupTable");
    assert(lookupTable);
    lookupTable->setLabel("Lookup Table");
    lookupTable->setHint("Colour lookup table");
    lookupTable->setScriptName("lookupTable");

    // define it as three dimensional
    lookupTable->setDimension(3);

    // label our dimensions are r/g/b
    lookupTable->setDimensionLabel("red", 0);
    lookupTable->setDimensionLabel("green", 1);
    lookupTable->setDimensionLabel("blue", 2);

    // set the UI colour for each dimension
    const OfxRGBColourD red   = {1,0,0};		//set red color to red curve
    const OfxRGBColourD green = {0,1,0};		//set green color to green curve
    const OfxRGBColourD blue  = {0,0,1};		//set blue color to blue curve
    lookupTable->setUIColour( 0, red );
    lookupTable->setUIColour( 1, green );
    lookupTable->setUIColour( 2, blue );

    // set the min/max parametric range to 0..1
    lookupTable->setRange(0.0, 1.0);

    // set a default curve, this example sets identity
    for(int component = 0; component < 3; ++component) {
      // add a control point at 0, value is 0
      lookupTable->addControlPoint(component, // curve to set
                                   0.0,   // time, ignored in this case, as we are not adding a key
                                   0.0,   // parametric position, zero
                                   0.0,   // value to be, 0
                                   false);   // don't add a key
      // add a control point at 1, value is 1
      lookupTable->addControlPoint(component, 0.0, 1.0, 1.0, false);
    }
  }
}

OFX::ImageEffect* RGBLutPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum context)
{
  return new RGBLutPlugin(handle);
}

namespace OFX
{
  namespace Plugin
  {
    void getPluginIDs(OFX::PluginFactoryArray &ids)
    {
      static RGBLutPluginFactory p("net.sf.openfx:RGBLutPlugin", 1, 0);
      ids.push_back(&p);
    }
  }
}
<commit_msg>add control point creation function<commit_after>/*
OFX RGBLut plugin, a plugin that illustrates the use of the OFX Support library.

Copyright (C) 2013 INRIA
Author Frederic Devernay frederic.devernay@inria.fr

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

  Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

  Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.

  Neither the name of the {organization} nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef _WINDOWS
#include <windows.h>
#endif

#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

#include <stdio.h>
#include "ofxsImageEffect.h"
#include "ofxsMultiThread.h"

#include "ofxsProcessing.H"

class RGBLutBase : public OFX::ImageProcessor {
protected :
  OFX::Image *_srcImg;
public :
  RGBLutBase(OFX::ImageEffect &instance): OFX::ImageProcessor(instance), _srcImg(0)
  {
  }
  void setSrcImg(OFX::Image *v) {_srcImg = v;}
};

// template to do the RGBA processing for discrete types
template <class PIX, int nComponents, int nValues>
class ImageRGBLutProcessor : public RGBLutBase
{
protected:
    PIX _lookupTable[3][nValues];
public :
  // ctor
  ImageRGBLutProcessor(OFX::ImageEffect &instance, const OFX::RenderArguments &args)
    : RGBLutBase(instance)
  {
    // build the LUT
    OFX::ParametricParam  *lookupTable = instance.fetchParametricParam("lookupTable");
    assert(lookupTable);
    for(int component = 0; component < 3; ++component) {
      for(PIX position = 0; position < nValues; ++position) {
        // position to evaluate the param at
        float parametricPos = float(position)/(nValues-1);

        // evaluate the parametric param
        double value = lookupTable->getValue(component, args.time, parametricPos);

        // set that in the lut
        _lookupTable[component][position] = std::max(PIX(0),std::min(PIX(value*(nValues-1)+0.5), PIX(nValues-1)));
      }
    }
  }
  // and do some processing
  void multiThreadProcessImages(OfxRectI procWindow)
  {
    assert(_dstImg);
    for(int y = procWindow.y1; y < procWindow.y2; y++)
    {
      if(_effect.abort())
        break;
      PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
      for(int x = procWindow.x1; x < procWindow.x2; x++)
      {
        PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
        if(srcPix)
        {
          for(int c = 0; c < nComponents; c++) {
            assert(0 <= srcPix[c] && srcPix[c] < nValues);
            dstPix[c] = _lookupTable[c][srcPix[c]];
          }
        }
        else
        {
          // no src pixel here, be black and transparent
          for(int c = 0; c < nComponents; c++)
            dstPix[c] = 0;
        }
        // increment the dst pixel
        dstPix += nComponents;
      }
    }
  }
};

// template to do the RGBA processing for floating-point types
template <int nComponents, int nValues>
class ImageRGBLutProcessorFloat : public RGBLutBase
{
protected:
    typedef float PIX;
    PIX _lookupTable[3][nValues];
public :
  // ctor
  ImageRGBLutProcessorFloat(OFX::ImageEffect &instance, const OFX::RenderArguments &args)
    : RGBLutBase(instance)
  {
    // build the LUT
    OFX::ParametricParam  *lookupTable = instance.fetchParametricParam("lookupTable");
    for(int component = 0; component < 3; ++component) {
      for(int position = 0; position < nValues; ++position) {
        // position to evaluate the param at
        double parametricPos = float(position)/(nValues-1);

        // evaluate the parametric param
        double value = lookupTable->getValue(component, args.time, parametricPos);
        //value = value * (nValues-1);
        //value = clamp(value, 0, nValues-1);

        // set that in the lut
        _lookupTable[component][position] = std::max(PIX(0),std::min(PIX(value),PIX(nValues-1)));
      }
    }
  }
  // and do some processing
  void multiThreadProcessImages(OfxRectI procWindow)
  {
    assert(_dstImg);
    for(int y = procWindow.y1; y < procWindow.y2; y++)
    {
      if(_effect.abort())
        break;
      PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
      for(int x = procWindow.x1; x < procWindow.x2; x++)
      {
        PIX *srcPix = (PIX *)  (_srcImg ? _srcImg->getPixelAddress(x, y) : 0);
        if(srcPix)
        {
          for(int c = 0; c < nComponents; c++) {
            dstPix[c] = interpolate(c, srcPix[c]);
          }
        }
        else
        {
          // no src pixel here, be black and transparent
          for(int c = 0; c < nComponents; c++)
            dstPix[c] = 0;
        }
        // increment the dst pixel
        dstPix += nComponents;
      }
    }
  }
private:
  float interpolate(int component, float value) {
    if (component == 3) { // alpha
      return value;
    }
    if (value < 0.) {
      return _lookupTable[component][0];
    } else if (value >= 1.) {
      return _lookupTable[component][nValues-1];
    } else {
      int i = (int)(value * (nValues-1));
      assert(i < nValues-1);
      float alpha = value - (float)i / (nValues-1);
      return _lookupTable[component][i] * (1.-alpha) + _lookupTable[component][i] * alpha;
    }
  }
};

////////////////////////////////////////////////////////////////////////////////
/** @brief The plugin that does our work */
class RGBLutPlugin : public OFX::ImageEffect
{
protected :
  OFX::Clip *dstClip_;
  OFX::Clip *srcClip_;

public :
  RGBLutPlugin(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , dstClip_(0)
    , srcClip_(0)
  {
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
  }

  virtual void render(const OFX::RenderArguments &args);
  void setupAndProcess(RGBLutBase &, const OFX::RenderArguments &args);
  void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName)
  {
    if (paramName=="addCtrlPts") {
      OFX::ParametricParam  *lookupTable = fetchParametricParam("lookupTable");
      for(int component = 0; component < 3; ++component) {
        int n = lookupTable->getNControlPoints(component, args.time);
        if (n <= 1) {
          // clear all control points
          lookupTable->deleteControlPoint(component);
          // add a control point at 0, value is 0
          lookupTable->addControlPoint(component, // curve to set
                                       args.time,   // time, ignored in this case, as we are not adding a key
                                       0.0,   // parametric position, zero
                                       0.0,   // value to be, 0
                                       false);   // don't add a key
          // add a control point at 1, value is 1
          lookupTable->addControlPoint(component, args.time, 1.0, 1.0, false);
        } else {
          std::pair<double, double> prev = lookupTable->getNthControlPoint(component, args.time, 0);
          for (int i = 1; i < n; ++i) {
            // note that getNthControlPoint is buggy in Nuke 6, and always returns point 1 for nthCtl > 0
            std::pair<double, double> next = lookupTable->getNthControlPoint(component, args.time, i);
            if (prev != next) { // don't create additional points if we encounter the Nuke bug
              // create a new control point between two existing control points
              double parametricPos = (prev.first + next.first)/2.;
              double parametricVal = lookupTable->getValue(component, args.time, parametricPos);
              lookupTable->addControlPoint(component, // curve to set
                                           args.time,   // time, ignored in this case, as we are not adding a key
                                           parametricPos,   // parametric position
                                           parametricVal,   // value to be, 0
                                           false);
            }
            prev = next;
          }
        }
      }
    }
  }
};

void RGBLutPlugin::setupAndProcess(RGBLutBase &processor, const OFX::RenderArguments &args)
{
  assert(dstClip_);
  std::auto_ptr<OFX::Image> dst(dstClip_->fetchImage(args.time));
  assert(srcClip_);
  std::auto_ptr<OFX::Image> src(srcClip_->fetchImage(args.time));

  if(src.get() && dst.get())
  {
    OFX::BitDepthEnum    srcBitDepth      = src->getPixelDepth();
    OFX::PixelComponentEnum srcComponents = src->getPixelComponents();
    OFX::BitDepthEnum dstBitDepth       = dst->getPixelDepth();
    OFX::PixelComponentEnum dstComponents  = dst->getPixelComponents();

    // see if they have the same depths and bytes and all
    if(srcBitDepth != dstBitDepth || srcComponents != dstComponents)
      throw int(1); // HACK!! need to throw an sensible exception here!
  }

  processor.setDstImg(dst.get());
  processor.setSrcImg(src.get());
  processor.setRenderWindow(args.renderWindow);
  processor.process();
}

void RGBLutPlugin::render(const OFX::RenderArguments &args)
{
  assert(dstClip_);
  OFX::BitDepthEnum       dstBitDepth    = dstClip_->getPixelDepth();
  OFX::PixelComponentEnum dstComponents  = dstClip_->getPixelComponents();

  if(dstComponents == OFX::ePixelComponentRGBA)
  {
    switch(dstBitDepth)
    {
    case OFX::eBitDepthUByte :
      {
        ImageRGBLutProcessor<unsigned char, 4, 256> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthUShort :
      {
        ImageRGBLutProcessor<unsigned short, 4, 65536> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthFloat :
      {
        ImageRGBLutProcessorFloat<4,1000> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;
    }
  }
  else {
    switch(dstBitDepth)
    {
    case OFX::eBitDepthUByte :
      {
        ImageRGBLutProcessor<unsigned char, 1, 256> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthUShort :
      {
        ImageRGBLutProcessor<unsigned short, 1, 65536> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;

    case OFX::eBitDepthFloat :
      {
        ImageRGBLutProcessorFloat<1,1000> fred(*this, args);
        setupAndProcess(fred, args);
      }
      break;
    }
  }
}

mDeclarePluginFactory(RGBLutPluginFactory, {}, {});

using namespace OFX;
void RGBLutPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
  desc.setLabels("RGBLut", "RGBLut", "RGBLut");
  desc.setPluginGrouping("OFX");
  desc.addSupportedContext(eContextFilter);
  desc.addSupportedBitDepth(eBitDepthUByte);
  desc.addSupportedBitDepth(eBitDepthUShort);
  desc.addSupportedBitDepth(eBitDepthFloat);

  desc.setSingleInstance(false);
  desc.setHostFrameThreading(false);
  desc.setSupportsMultiResolution(true);
  desc.setSupportsTiles(true);
  desc.setTemporalClipAccess(false);
  desc.setRenderTwiceAlways(false);
  desc.setSupportsMultipleClipPARs(false);

  if (!OFX::getImageEffectHostDescription()->supportsParametricParameter) {
	throwHostMissingSuiteException(kOfxParametricParameterSuite);
  }
}

void RGBLutPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context)
{
  ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
  assert(srcClip);
  srcClip->addSupportedComponent(ePixelComponentRGBA);
  srcClip->addSupportedComponent(ePixelComponentAlpha);
  srcClip->setTemporalClipAccess(false);
  srcClip->setSupportsTiles(true);
  srcClip->setIsMask(false);

  ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
  assert(dstClip);
  dstClip->addSupportedComponent(ePixelComponentRGBA);
  dstClip->addSupportedComponent(ePixelComponentAlpha);
  dstClip->setSupportsTiles(true);

  if (OFX::getImageEffectHostDescription()->supportsParametricParameter) {
    // define it
    OFX::ParametricParamDescriptor* lookupTable = desc.defineParametricParam("lookupTable");
    assert(lookupTable);
    lookupTable->setLabel("Lookup Table");
    lookupTable->setHint("Colour lookup table");
    lookupTable->setScriptName("lookupTable");

    // define it as three dimensional
    lookupTable->setDimension(3);

    // label our dimensions are r/g/b
    lookupTable->setDimensionLabel("red", 0);
    lookupTable->setDimensionLabel("green", 1);
    lookupTable->setDimensionLabel("blue", 2);

    // set the UI colour for each dimension
    const OfxRGBColourD red   = {1,0,0};		//set red color to red curve
    const OfxRGBColourD green = {0,1,0};		//set green color to green curve
    const OfxRGBColourD blue  = {0,0,1};		//set blue color to blue curve
    lookupTable->setUIColour( 0, red );
    lookupTable->setUIColour( 1, green );
    lookupTable->setUIColour( 2, blue );

    // set the min/max parametric range to 0..1
    lookupTable->setRange(0.0, 1.0);

    // set a default curve, this example sets identity
    for(int component = 0; component < 3; ++component) {
      // add a control point at 0, value is 0
      lookupTable->addControlPoint(component, // curve to set
                                   0.0,   // time, ignored in this case, as we are not adding a key
                                   0.0,   // parametric position, zero
                                   0.0,   // value to be, 0
                                   false);   // don't add a key
      // add a control point at 1, value is 1
      lookupTable->addControlPoint(component, 0.0, 1.0, 1.0, false);
    }
    OFX::PushButtonParamDescriptor* addCtrlPts = desc.definePushButtonParam("addCtrlPts");
    addCtrlPts->setLabels("Add Control Points", "Add Control Points", "Add Control Points");
  }
}

OFX::ImageEffect* RGBLutPluginFactory::createInstance(OfxImageEffectHandle handle, OFX::ContextEnum context)
{
  return new RGBLutPlugin(handle);
}

namespace OFX
{
  namespace Plugin
  {
    void getPluginIDs(OFX::PluginFactoryArray &ids)
    {
      static RGBLutPluginFactory p("net.sf.openfx:RGBLutPlugin", 1, 0);
      ids.push_back(&p);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * RWLock
 * Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
 * Copyright (C) 2011 by NeoSmart Technologies
 * This code is released under the terms of the MIT License
*/

#include "stdafx.h"
#include "RWLock.h"

#include <tchar.h>
#include <assert.h>
#include <stdlib.h>

__forceinline __int16 ReaderCount(unsigned __int32 lock)
{
	return lock & 0x00007FFF;
}

__forceinline __int32 SetReaders(unsigned __int32 lock, unsigned __int16 readers)
{
	return (lock & ~0x00007FFF) | readers;
}

__forceinline __int16 WaitingCount(unsigned __int32 lock)
{
	return (lock & 0x3FFF8000) >> 15;
}

__forceinline __int32 SetWaiting(unsigned __int32 lock, unsigned __int16 waiting)
{
	return (lock & ~0x3FFF8000) | (waiting << 15);
}

__forceinline bool Writer(unsigned __int32 lock)
{
	return (lock & 0x40000000) != 0;
}

__forceinline __int32 SetWriter(unsigned __int32 lock, bool writer)
{
	if(writer)
		return lock | 0x40000000;
	else
		return lock & ~0x40000000;
}

__forceinline bool AllClear(unsigned __int32 lock)
{
	return (lock & 0x40007FFF) == 0;
}

__forceinline bool Initialized(unsigned __int32 lock)
{
	return (lock & 0x80000000) != 0;
}

__forceinline __int32 SetInitialized(unsigned __int32 lock, bool initialized)
{
	if(initialized)
		return lock | 0x80000000;
	else
		return lock & ~0x80000000;
}

RWLockIPC::RWLockIPC(unsigned __int32 *lock, LPCTSTR guid)
{
	SECURITY_ATTRIBUTES sa;
	SECURITY_DESCRIPTOR sd;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = &sd;
	InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
	SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

	_lock = lock;

	//Create local volatile pointer for double-checked locking to work
	volatile unsigned __int32 *vLock = lock;

	_event = CreateEvent(&sa, FALSE, FALSE, guid);

	if(!Initialized(*vLock))
	{
		HANDLE hMutex = CreateMutex(&sa, FALSE, guid);
		WaitForSingleObject(hMutex, INFINITE);

		if(!Initialized(*vLock))
		{
			*vLock = RWLOCK_INIT;
			*vLock = SetInitialized(*vLock, true);
		}

		ReleaseMutex(hMutex);
		CloseHandle(hMutex);
	}
}

RWLockIPC::~RWLockIPC()
{
	CloseHandle(_event);
}

void RWLockIPC::StartRead()
{
	for(int i = 0; ; ++i)
	{
		__int32 temp = *_lock;
		if(!Writer(temp))
		{
			if(InterlockedCompareExchange((LONG*)_lock, SetReaders(temp, ReaderCount(temp) + 1), temp) == temp)
				return;
			else
				continue;
		}
		else
		{
			if(i < MAX_SPIN)
			{
				YieldProcessor();
				continue;
			}

			//The pending write operation is taking too long, so we'll drop to the kernel and wait
			if(InterlockedCompareExchange((LONG*)_lock, SetWaiting(temp, WaitingCount(temp) + 1), temp) != temp)
				continue;

			i = 0; //Reset the spincount for the next time
			WaitForSingleObject(_event, INFINITE);

			do
			{
				temp = *_lock;
			} while(InterlockedCompareExchange((LONG*)_lock, SetWaiting(temp, WaitingCount(temp) - 1), temp) != temp);
		}
	}
}

void RWLockIPC::StartWrite()
{
	for(int i = 0; ; ++i)
	{
		__int32 temp = *_lock;
		if(AllClear(temp))
		{
			if(InterlockedCompareExchange((LONG*)_lock, SetWriter(temp, true), temp) == temp)
				return;
			else
				continue;
		}
		else
		{
			if(i < MAX_SPIN)
			{
				YieldProcessor();
				continue;
			}

			//The pending read operations are taking too long, so we'll drop to the kernel and wait
			if(InterlockedCompareExchange((LONG*)_lock, SetWaiting(temp, WaitingCount(temp) + 1), temp) != temp)
				continue;

			i = 0; //Reset the spincount for the next time
			WaitForSingleObject(_event, INFINITE);

			do
			{
				temp = *_lock;
			} while(InterlockedCompareExchange((LONG*)_lock, SetWaiting(temp, WaitingCount(temp) - 1), temp) != temp);
		}
	}
}

void RWLockIPC::EndRead()
{
	while(true)
	{
		__int32 temp = *_lock;
		assert(ReaderCount(temp) > 0);

		if(ReaderCount(temp) == 1 && WaitingCount(temp) != 0)
		{
			//Note: this isn't nor has to be thread-safe, as the worst a duplicate notification can do
			//is cause a waiting to reader to wake, perform a spinlock, then go back to sleep

			//We're the last reader and there's a pending write
			//Wake one waiting writer
			SetEvent(_event);
		}

		//Decrement reader count
		if(InterlockedCompareExchange((LONG*)_lock, SetReaders(temp, ReaderCount(temp) - 1), temp) == temp)
			break;
	}
}

void RWLockIPC::EndWrite()
{
	while(true)
	{
		__int32 temp;

		while(true)
		{
			temp = *_lock;
			assert(Writer(temp));
			if(WaitingCount(temp) == 0)
				break;

			//Note: this is thread-safe (there's guaranteed not to be another EndWrite simultaneously)
			//Wake all waiting readers or writers, loop until wake confirmation is received
			SetEvent(_event);
		}

		//Decrement writer count
		if(InterlockedCompareExchange((LONG*)_lock, SetWriter(temp, false), temp) == temp)
			break;
	}
}

RWLock::RWLock()
	: _rwLock(&(*(_lock = (new unsigned int)) = RWLOCK_INIT), NULL)
{
}

RWLock::~RWLock()
{
	delete _lock;
}

void RWLock::StartRead()
{
	_rwLock.StartRead();
}

void RWLock::StartWrite()
{
	_rwLock.StartWrite();
}

void RWLock::EndRead()
{
	_rwLock.EndRead();
}

void RWLock::EndWrite()
{
	_rwLock.EndWrite();
}

struct THREAD_ENTRY
{
	SLIST_ENTRY ItemEntry;
	unsigned int* ThreadPointer;
};

RWLockIPCReentrant::RWLockIPCReentrant(unsigned __int32 *lock, LPCTSTR guid)
	: _rwLock(lock, guid)
{
	_tlsIndex = TlsAlloc();

	_threadPointers = (PSLIST_HEADER)_aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
	InitializeSListHead(_threadPointers);
}

RWLockIPCReentrant::~RWLockIPCReentrant()
{
	THREAD_ENTRY *entry;
	while((entry = (THREAD_ENTRY*) InterlockedPopEntrySList(_threadPointers)) != NULL)
	{
		delete entry->ThreadPointer;
		_aligned_free(entry);
	}

	_aligned_free(_threadPointers);

	TlsFree(_tlsIndex);
}

void RWLockIPCReentrant::StartRead()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	if(InterlockedIncrement((LONG*)threadCounter) == 1)
		_rwLock.StartRead();
}

void RWLockIPCReentrant::StartWrite()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	if(InterlockedIncrement((LONG*)threadCounter) == 1)
		_rwLock.StartWrite();
}

void RWLockIPCReentrant::EndRead()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	assert(*threadCounter > 0);
	if(InterlockedDecrement((LONG*)threadCounter) == 0)
		_rwLock.EndRead();
}

void RWLockIPCReentrant::EndWrite()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	assert(*threadCounter > 0);
	if(InterlockedDecrement((LONG*)threadCounter) == 0)
		_rwLock.EndWrite();
}

RWLockReentrant::RWLockReentrant()
	: _rwLock(&(*(_lock = (new unsigned int)) = RWLOCK_INIT), NULL)
{
}

RWLockReentrant::~RWLockReentrant()
{
	delete _lock;
}

void RWLockReentrant::StartRead()
{
	_rwLock.StartRead();
}

void RWLockReentrant::StartWrite()
{
	_rwLock.StartWrite();
}

void RWLockReentrant::EndRead()
{
	_rwLock.EndRead();
}

void RWLockReentrant::EndWrite()
{
	_rwLock.EndWrite();
}
<commit_msg>Removed typecasts not needed on VS2010<commit_after>/*
 * RWLock
 * Author: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
 * Copyright (C) 2011 by NeoSmart Technologies
 * This code is released under the terms of the MIT License
*/

#include "stdafx.h"
#include "RWLock.h"

#include <tchar.h>
#include <assert.h>
#include <stdlib.h>

__forceinline __int16 ReaderCount(unsigned __int32 lock)
{
	return lock & 0x00007FFF;
}

__forceinline __int32 SetReaders(unsigned __int32 lock, unsigned __int16 readers)
{
	return (lock & ~0x00007FFF) | readers;
}

__forceinline __int16 WaitingCount(unsigned __int32 lock)
{
	return (lock & 0x3FFF8000) >> 15;
}

__forceinline __int32 SetWaiting(unsigned __int32 lock, unsigned __int16 waiting)
{
	return (lock & ~0x3FFF8000) | (waiting << 15);
}

__forceinline bool Writer(unsigned __int32 lock)
{
	return (lock & 0x40000000) != 0;
}

__forceinline __int32 SetWriter(unsigned __int32 lock, bool writer)
{
	if(writer)
		return lock | 0x40000000;
	else
		return lock & ~0x40000000;
}

__forceinline bool AllClear(unsigned __int32 lock)
{
	return (lock & 0x40007FFF) == 0;
}

__forceinline bool Initialized(unsigned __int32 lock)
{
	return (lock & 0x80000000) != 0;
}

__forceinline __int32 SetInitialized(unsigned __int32 lock, bool initialized)
{
	if(initialized)
		return lock | 0x80000000;
	else
		return lock & ~0x80000000;
}

RWLockIPC::RWLockIPC(unsigned __int32 *lock, LPCTSTR guid)
{
	SECURITY_ATTRIBUTES sa;
	SECURITY_DESCRIPTOR sd;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = &sd;
	InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
	SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);

	_lock = lock;

	//Create local volatile pointer for double-checked locking to work
	volatile unsigned __int32 *vLock = lock;

	_event = CreateEvent(&sa, FALSE, FALSE, guid);

	if(!Initialized(*vLock))
	{
		HANDLE hMutex = CreateMutex(&sa, FALSE, guid);
		WaitForSingleObject(hMutex, INFINITE);

		if(!Initialized(*vLock))
		{
			*vLock = RWLOCK_INIT;
			*vLock = SetInitialized(*vLock, true);
		}

		ReleaseMutex(hMutex);
		CloseHandle(hMutex);
	}
}

RWLockIPC::~RWLockIPC()
{
	CloseHandle(_event);
}

void RWLockIPC::StartRead()
{
	for(int i = 0; ; ++i)
	{
		__int32 temp = *_lock;
		if(!Writer(temp))
		{
			if(InterlockedCompareExchange(_lock, SetReaders(temp, ReaderCount(temp) + 1), temp) == temp)
				return;
			else
				continue;
		}
		else
		{
			if(i < MAX_SPIN)
			{
				YieldProcessor();
				continue;
			}

			//The pending write operation is taking too long, so we'll drop to the kernel and wait
			if(InterlockedCompareExchange(_lock, SetWaiting(temp, WaitingCount(temp) + 1), temp) != temp)
				continue;

			i = 0; //Reset the spincount for the next time
			WaitForSingleObject(_event, INFINITE);

			do
			{
				temp = *_lock;
			} while(InterlockedCompareExchange(_lock, SetWaiting(temp, WaitingCount(temp) - 1), temp) != temp);
		}
	}
}

void RWLockIPC::StartWrite()
{
	for(int i = 0; ; ++i)
	{
		__int32 temp = *_lock;
		if(AllClear(temp))
		{
			if(InterlockedCompareExchange(_lock, SetWriter(temp, true), temp) == temp)
				return;
			else
				continue;
		}
		else
		{
			if(i < MAX_SPIN)
			{
				YieldProcessor();
				continue;
			}

			//The pending read operations are taking too long, so we'll drop to the kernel and wait
			if(InterlockedCompareExchange(_lock, SetWaiting(temp, WaitingCount(temp) + 1), temp) != temp)
				continue;

			i = 0; //Reset the spincount for the next time
			WaitForSingleObject(_event, INFINITE);

			do
			{
				temp = *_lock;
			} while(InterlockedCompareExchange(_lock, SetWaiting(temp, WaitingCount(temp) - 1), temp) != temp);
		}
	}
}

void RWLockIPC::EndRead()
{
	while(true)
	{
		__int32 temp = *_lock;
		assert(ReaderCount(temp) > 0);

		if(ReaderCount(temp) == 1 && WaitingCount(temp) != 0)
		{
			//Note: this isn't nor has to be thread-safe, as the worst a duplicate notification can do
			//is cause a waiting to reader to wake, perform a spinlock, then go back to sleep

			//We're the last reader and there's a pending write
			//Wake one waiting writer
			SetEvent(_event);
		}

		//Decrement reader count
		if(InterlockedCompareExchange(_lock, SetReaders(temp, ReaderCount(temp) - 1), temp) == temp)
			break;
	}
}

void RWLockIPC::EndWrite()
{
	while(true)
	{
		__int32 temp;

		while(true)
		{
			temp = *_lock;
			assert(Writer(temp));
			if(WaitingCount(temp) == 0)
				break;

			//Note: this is thread-safe (there's guaranteed not to be another EndWrite simultaneously)
			//Wake all waiting readers or writers, loop until wake confirmation is received
			SetEvent(_event);
		}

		//Decrement writer count
		if(InterlockedCompareExchange(_lock, SetWriter(temp, false), temp) == temp)
			break;
	}
}

RWLock::RWLock()
	: _rwLock(&(*(_lock = (new unsigned int)) = RWLOCK_INIT), NULL)
{
}

RWLock::~RWLock()
{
	delete _lock;
}

void RWLock::StartRead()
{
	_rwLock.StartRead();
}

void RWLock::StartWrite()
{
	_rwLock.StartWrite();
}

void RWLock::EndRead()
{
	_rwLock.EndRead();
}

void RWLock::EndWrite()
{
	_rwLock.EndWrite();
}

struct THREAD_ENTRY
{
	SLIST_ENTRY ItemEntry;
	unsigned int* ThreadPointer;
};

RWLockIPCReentrant::RWLockIPCReentrant(unsigned __int32 *lock, LPCTSTR guid)
	: _rwLock(lock, guid)
{
	_tlsIndex = TlsAlloc();

	_threadPointers = (PSLIST_HEADER)_aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
	InitializeSListHead(_threadPointers);
}

RWLockIPCReentrant::~RWLockIPCReentrant()
{
	THREAD_ENTRY *entry;
	while((entry = (THREAD_ENTRY*) InterlockedPopEntrySList(_threadPointers)) != NULL)
	{
		delete entry->ThreadPointer;
		_aligned_free(entry);
	}

	_aligned_free(_threadPointers);

	TlsFree(_tlsIndex);
}

void RWLockIPCReentrant::StartRead()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	if(InterlockedIncrement(threadCounter) == 1)
		_rwLock.StartRead();
}

void RWLockIPCReentrant::StartWrite()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	if(InterlockedIncrement(threadCounter) == 1)
		_rwLock.StartWrite();
}

void RWLockIPCReentrant::EndRead()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	assert(*threadCounter > 0);
	if(InterlockedDecrement(threadCounter) == 0)
		_rwLock.EndRead();
}

void RWLockIPCReentrant::EndWrite()
{
	unsigned int *threadCounter = (unsigned int*)TlsGetValue(_tlsIndex);
	if(threadCounter == NULL)
	{
		threadCounter = new unsigned int;
		*threadCounter = 0;
		TlsSetValue(_tlsIndex, threadCounter);
		THREAD_ENTRY *entry = (THREAD_ENTRY*)_aligned_malloc(sizeof(THREAD_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
		entry->ThreadPointer = threadCounter;
		InterlockedPushEntrySList(_threadPointers, &(entry->ItemEntry));
	}
	assert(*threadCounter > 0);
	if(InterlockedDecrement(threadCounter) == 0)
		_rwLock.EndWrite();
}

RWLockReentrant::RWLockReentrant()
	: _rwLock(&(*(_lock = (new unsigned int)) = RWLOCK_INIT), NULL)
{
}

RWLockReentrant::~RWLockReentrant()
{
	delete _lock;
}

void RWLockReentrant::StartRead()
{
	_rwLock.StartRead();
}

void RWLockReentrant::StartWrite()
{
	_rwLock.StartWrite();
}

void RWLockReentrant::EndRead()
{
	_rwLock.EndRead();
}

void RWLockReentrant::EndWrite()
{
	_rwLock.EndWrite();
}
<|endoftext|>


<commit_before>/* @doc \file Object to generate a file following AMELIF format.

   Copyright (c) 2007-2010
   @author Olivier Stasse
   JRL-Japan, CNRS/AIST

   All rights reserved.

   Please refers to file License.txt for details on the license.

*/

#include <string>
#include <iostream>
#include <fstream>
#include <dynamicsJRLJapan/dynamicsJRLJapanFactory.h>
#include "CommonTools.h"

using namespace std;
using namespace dynamicsJRLJapan;

void DisplayDynamicRobotInformation(CjrlDynamicRobot *aDynamicRobot,
				    ostream &tcout)
{
  std::vector<CjrlJoint *> aVec = aDynamicRobot->jointVector();
  int r = aVec.size();
  tcout << "Number of joints :" << r << endl;

}

int main(int argc, char *argv[])
{
  string aSpecificitiesFileName;
  string aPath;
  string aName;
  string aMapFromJointToRank;

  ofstream tcout("output.txt",ofstream::out);

  if (argc!=5)
    {
      aPath="./";
      aName="sample.wrl";
      aSpecificitiesFileName = "sampleSpecificities.xml";
      aMapFromJointToRank = "sampleLinkJointRank.xml";
    }
  else
    {
      aSpecificitiesFileName = argv[3];
      aPath=argv[1];
      aName=argv[2];
      aMapFromJointToRank=argv[4];
    }
  dynamicsJRLJapan::ObjectFactory aRobotDynamicsObjectConstructor;

  CjrlHumanoidDynamicRobot * aHDR = aRobotDynamicsObjectConstructor.createHumanoidDynamicRobot();

  if (aHDR==0)
    {
      cerr<< "Dynamic cast on HDR failed " << endl;
      exit(-1);
    }
  string RobotFileName = aPath+aName;
  dynamicsJRLJapan::parseOpenHRPVRMLFile(*aHDR,RobotFileName,aMapFromJointToRank,aSpecificitiesFileName);

  // Display tree of the joints.
  CjrlJoint* rootJoint = aHDR->rootJoint();

  int NbOfDofs = aHDR->numberDof();
  tcout << "NbOfDofs :" << NbOfDofs << std::endl;
  if (NbOfDofs==0)
    {
      cerr << "Empty Robot..."<< endl;
      return -1;
    }
  MAL_VECTOR_DIM(aCurrentConf,double,NbOfDofs);
  int lindex=0;
  for(int i=0;i<6;i++)
    aCurrentConf[lindex++] = 0.0;
  aCurrentConf[2] = 0.705;
  for(int i=0;i<(NbOfDofs-6 < 40 ? NbOfDofs-6 : 40) ;i++)
  aCurrentConf[lindex++] = 0.0;
 /* aCurrentConf[8]= -0.4538;
  aCurrentConf[9]= 0.8727;
  aCurrentConf[10]= -0.4189;
  aCurrentConf[14]= -0.4538;
  aCurrentConf[15]= 0.8727;
  aCurrentConf[16]= -0.4189;
  aCurrentConf[22]= 0.2618;
  aCurrentConf[23]= -0.1745;
  aCurrentConf[25]= -0.5236;
  aCurrentConf[28]=  0.1745;
  aCurrentConf[29]= 0.2618;
  aCurrentConf[30]= 0.1745;
  aCurrentConf[32]= -0.5236;
  aCurrentConf[35]= 0.1745; */
  tcout << "NbOfDofs:" << NbOfDofs << std::endl;
  tcout << "Current Configuration :" << aCurrentConf << std::endl;
  aHDR->currentConfiguration(aCurrentConf);

  MAL_VECTOR_DIM(aCurrentVel,double,NbOfDofs);
  lindex=0;
  for(int i=0;i<NbOfDofs;i++)
    aCurrentVel[lindex++] = 0.0;
  aCurrentVel[6]=1.0;
  aCurrentVel[7]=1.0;
  aCurrentVel[8]=1.0;
  aCurrentVel[9]=1.0;

  MAL_S3_VECTOR(ZMPval,double);

  aHDR->currentVelocity(aCurrentVel);
  //MAL_VECTOR_FILL(aCurrentVel,0.0);
  MAL_VECTOR_DIM(aCurrentAcc,double,NbOfDofs);
  MAL_VECTOR_FILL(aCurrentAcc,0.0);
  aCurrentAcc[7]=2.0;
  aCurrentAcc[10]=2.0;
  aHDR->currentAcceleration(aCurrentAcc);

  //  aHDR->setComputeZMP(true);
  // This is mandatory for this implementation of computeForwardKinematics
  // to compute the derivative of the momentum.
  {
    string inProperty[5]={"TimeStep","ComputeAcceleration",
			  "ComputeBackwardDynamics", "ComputeZMP","ComputeAccelerationCoM"};
    string inValue[5]={"0.005","true","true","true","true"};
    for(unsigned int i=0;i<5;i++)
      aHDR->setProperty(inProperty[i],inValue[i]);

  }

  aHDR->computeForwardKinematics();
  ZMPval = aHDR->zeroMomentumPoint();
  tcout << "First value of ZMP : "
	<< filterprecision(ZMPval(0)) << " "
	<< filterprecision(ZMPval(1)) << " "
	<< filterprecision(ZMPval(2)) << endl;
  MAL_S3_VECTOR(poscom,double);
  poscom = aHDR->positionCenterOfMass();
  tcout << "Should be equal to the CoM: "
	<< filterprecision(poscom(0)) << " "
	<< filterprecision(poscom(1)) << " "
	<< filterprecision(poscom(2)) << endl;

  matrixNxP InertiaMatrix;
  aHDR->computeInertiaMatrix();
  InertiaMatrix = aHDR->inertiaMatrix();

  tcout << "InertiaMatrix("
       << MAL_MATRIX_NB_ROWS(InertiaMatrix)<< ","
       << MAL_MATRIX_NB_COLS(InertiaMatrix)<< ")"<< endl;

  DisplayMatrix(InertiaMatrix,tcout);

  ofstream aof;
  aof.open("InertiaMatrix.dat");
  for(unsigned int i=0;i<MAL_MATRIX_NB_ROWS(InertiaMatrix);i++)
    {
      for(unsigned int j=0;j<MAL_MATRIX_NB_COLS(InertiaMatrix);j++)
       {
         aof << InertiaMatrix(i,j) << " ";
       }
      aof << endl;
    }
  aof.close();

  std::vector<CjrlJoint *> aVec = aHDR->jointVector();

  // Get the Jacobian of the right ankle.
  CjrlJoint  * aJoint = aHDR->rightAnkle();
  aJoint->computeJacobianJointWrtConfig();

  tcout << "Jacobian of the right ankle." << endl;
  MAL_MATRIX(,double) aJ;
  aJ = aJoint->jacobianJointWrtConfig();
  DisplayMatrix(aJ,tcout);

  // Get the articular Jacobian from the right ankle to the right wrist.
  vector3d origin; origin(0) = 0.0; origin(1) = 0.0; origin(2) = 0.0;
  aHDR->getJacobian(*aHDR->rightAnkle(),
		    *aHDR->rightWrist(),
		    origin,
		    aJ);
  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);
  MAL_MATRIX_RESIZE(aJ,3, MAL_MATRIX_NB_COLS(aJ));
  // Get the linear part of the articular Jacobian from the right ankle to the right wrist.
  aHDR->getPositionJacobian(*aHDR->rightAnkle(),
			    *aHDR->rightWrist(),
			    origin,
			    aJ);
  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);

  // Get the angular part of the articular Jacobian from the right ankle to the right wrist.
  aHDR->getOrientationJacobian(*aHDR->rightAnkle(),
			       *aHDR->rightWrist(),
			       aJ);

  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);

  tcout << "****************************" << endl;
  rootJoint->computeJacobianJointWrtConfig();
  aJ = rootJoint->jacobianJointWrtConfig();

  tcout << "Rank of Root: " << rootJoint->rankInConfiguration() << endl;

  //  DisplayMatrix(aJ);

  aJoint = aHDR->waist();
  tcout << "****************************" << endl;
  aHDR->computeJacobianCenterOfMass();
  DisplayMatrix(aHDR->jacobianCenterOfMass(),tcout);
  tcout << "****************************" << endl;
  RecursiveDisplayOfJoints(rootJoint,tcout,10);

  tcout << "****************************" << endl;

  // Test rank of the hands.
  tcout << "Rank of the right hand "<< endl;
  tcout << aHDR->rightWrist()->rankInConfiguration() << endl;
  CjrlHand *rightHand = aHDR->rightHand();
  string empty("");
  DisplayHand(rightHand,empty,tcout);

  tcout << "Rank of the left hand "<< endl;
  tcout << aHDR->leftWrist()->rankInConfiguration() << endl;
  CjrlHand *leftHand = aHDR->leftHand();
  DisplayHand(leftHand,empty,tcout);

  // Test rank of the feet.
  tcout << "Rank of the right foot "<< endl;
  tcout << aHDR->rightFoot()->associatedAnkle()->rankInConfiguration() << endl;
  CjrlFoot *rightFoot = aHDR->rightFoot();
  DisplayFoot(rightFoot,empty,tcout);

  tcout << "Rank of the left foot "<< endl;
  tcout << aHDR->leftFoot()->associatedAnkle()->rankInConfiguration() << endl;
  CjrlFoot *leftFoot = aHDR->leftFoot();
  DisplayFoot(leftFoot,empty,tcout);

  tcout << "Current transformation of left Ankle."<< endl;
  dm4d(aHDR->leftAnkle()->currentTransformation(),tcout,empty);
  tcout << endl;
  tcout << "Current transformation of right Ankle."<< endl;
  dm4d(aHDR->rightAnkle()->currentTransformation(),tcout,empty);
  tcout << endl;

  for(int i=0;i<4;i++)
    {
      aHDR->currentVelocity(aCurrentVel);
      aHDR->currentAcceleration(aCurrentAcc);
      aHDR->computeForwardKinematics();
      ZMPval = aHDR->zeroMomentumPoint();
      tcout << i << "-th value of ZMP : "
	    << filterprecision(ZMPval(0)) << " "
	    << filterprecision(ZMPval(1)) << " "
	    << filterprecision(ZMPval(2)) << endl;
      poscom = aHDR->positionCenterOfMass();
      tcout << "Should be equal to the CoM: "
	    << filterprecision(poscom(0)) << " "
	    << filterprecision(poscom(1)) << " "
	    << filterprecision(poscom(2)) << endl;
    }

  // Check the information on actuated joints.
  std::vector<CjrlJoint *> ActuatedJoints = aHDR->getActuatedJoints();

  tcout << "Size of actuated Joints:" << ActuatedJoints.size() << endl;
  for(unsigned int i=0;i<ActuatedJoints.size();i++)
    tcout << "Rank of actuated joints ("<<i<< ") in configuration :"
	  << ActuatedJoints[i]->rankInConfiguration() << endl;

  tcout << "Humanoid mass:" << aHDR->mass() << endl;

  DisplayForces(aHDR,empty,tcout);
  DisplayTorques(aHDR,empty, tcout);

  // Test torques.

  //double dynamicDrift [] = { 0,0,0,0,0,0, 0.00106856, -3.65827, -3.24512, 3.39716, -0.0415928, -0.0752126, -2.19959e-016, 3.65805, -3.2449, 3.38531, -0.0423655, 0.0753855, 1.11009e-016, 4.43083, -2.0292e-020, -0.12657, 1.03213, -2.57379, -0.499568, -1.39763, -0.00344316, -0.302932, -0.00679369, 1.07342, 2.5637, 0.489739, -1.35744, -2.65727e-005, -0.262741, 0.00685521 };
  tcout << "Test Torques:" << endl;
  const matrixNxP& Torques = aHDR->currentTorques();
  for(unsigned int i=6;i<MAL_MATRIX_NB_ROWS(Torques);i++)
    {
      double torquefrominertia = 9.81 * InertiaMatrix(i,2);
      tcout << filterprecision(Torques(i,0)) << " "
	    << filterprecision(torquefrominertia) << " \t DD \t " << Torques(i,0)-torquefrominertia << endl;
    }
  tcout << "Test Linear Velocity:" << endl;
  DisplayLinearVelocity(aHDR,tcout);
  tcout << "Test Angular Velocity:" << endl;
  DisplayAngularVelocity(aHDR,tcout);

  tcout << "Test Linear Acceleration:" << endl;
  DisplayLinearAcceleration(aHDR,tcout);
  tcout << "Test Angular Acceleration:" << endl;
  DisplayAngularAcceleration(aHDR,tcout);

  tcout.close();

  // ASCII Comparison between the generated output and the reference one
  // given in argument.
  if (argc==2)
    {
      char OurFileName[120]="output.txt";
      char ReportFileName[120]="reportthdr.txt";
      if (CompareTwoFiles(argv[1],
			  OurFileName,
			  ReportFileName))
	{
	  delete aHDR;
	  return 0;
	}
    }
  delete aHDR;
  return -1;
}
<commit_msg>Include new tests asked by user.<commit_after>/* @doc \file Object to generate a file following AMELIF format.

   Copyright (c) 2007-2010
   @author Olivier Stasse
   JRL-Japan, CNRS/AIST

   All rights reserved.

   Please refers to file License.txt for details on the license.

*/

#include <string>
#include <iostream>
#include <fstream>
#include <dynamicsJRLJapan/dynamicsJRLJapanFactory.h>
#include "CommonTools.h"

using namespace std;
using namespace dynamicsJRLJapan;

void DisplayDynamicRobotInformation(CjrlDynamicRobot *aDynamicRobot,
				    ostream &tcout)
{
  std::vector<CjrlJoint *> aVec = aDynamicRobot->jointVector();
  int r = aVec.size();
  tcout << "Number of joints :" << r << endl;

}

int main(int argc, char *argv[])
{
  string aSpecificitiesFileName;
  string aPath;
  string aName;
  string aMapFromJointToRank;

  ofstream tcout("output.txt",ofstream::out);

  if (argc!=5)
    {
      aPath="./";
      aName="sample.wrl";
      aSpecificitiesFileName = "sampleSpecificities.xml";
      aMapFromJointToRank = "sampleLinkJointRank.xml";
    }
  else
    {
      aSpecificitiesFileName = argv[3];
      aPath=argv[1];
      aName=argv[2];
      aMapFromJointToRank=argv[4];
    }
  dynamicsJRLJapan::ObjectFactory aRobotDynamicsObjectConstructor;

  CjrlHumanoidDynamicRobot * aHDR = aRobotDynamicsObjectConstructor.createHumanoidDynamicRobot();

  if (aHDR==0)
    {
      cerr<< "Dynamic cast on HDR failed " << endl;
      exit(-1);
    }
  string RobotFileName = aPath+aName;
  dynamicsJRLJapan::parseOpenHRPVRMLFile(*aHDR,RobotFileName,aMapFromJointToRank,aSpecificitiesFileName);

  // Display tree of the joints.
  CjrlJoint* rootJoint = aHDR->rootJoint();

  int NbOfDofs = aHDR->numberDof();
  tcout << "NbOfDofs :" << NbOfDofs << std::endl;
  if (NbOfDofs==0)
    {
      cerr << "Empty Robot..."<< endl;
      return -1;
    }
  MAL_VECTOR_DIM(aCurrentConf,double,NbOfDofs);
  int lindex=0;
  for(int i=0;i<6;i++)
    aCurrentConf[lindex++] = 0.0;
  aCurrentConf[2] = 0.705;
  for(int i=0;i<(NbOfDofs-6 < 40 ? NbOfDofs-6 : 40) ;i++)
  aCurrentConf[lindex++] = 0.0;
 /* aCurrentConf[8]= -0.4538;
  aCurrentConf[9]= 0.8727;
  aCurrentConf[10]= -0.4189;
  aCurrentConf[14]= -0.4538;
  aCurrentConf[15]= 0.8727;
  aCurrentConf[16]= -0.4189;
  aCurrentConf[22]= 0.2618;
  aCurrentConf[23]= -0.1745;
  aCurrentConf[25]= -0.5236;
  aCurrentConf[28]=  0.1745;
  aCurrentConf[29]= 0.2618;
  aCurrentConf[30]= 0.1745;
  aCurrentConf[32]= -0.5236;
  aCurrentConf[35]= 0.1745; */
  tcout << "NbOfDofs:" << NbOfDofs << std::endl;
  tcout << "Current Configuration :" << aCurrentConf << std::endl;
  aHDR->currentConfiguration(aCurrentConf);

  MAL_VECTOR_DIM(aCurrentVel,double,NbOfDofs);
  lindex=0;
  for(int i=0;i<NbOfDofs;i++)
    aCurrentVel[lindex++] = 0.0;
  aCurrentVel[3]=1.0;
  aCurrentVel[2]=100.0;
  aCurrentVel[6]=1.0;
  aCurrentVel[8]=0.0;

  MAL_S3_VECTOR(ZMPval,double);

  aHDR->currentVelocity(aCurrentVel);
  //MAL_VECTOR_FILL(aCurrentVel,0.0);
  MAL_VECTOR_DIM(aCurrentAcc,double,NbOfDofs);
  MAL_VECTOR_FILL(aCurrentAcc,0.0);
  aHDR->currentAcceleration(aCurrentAcc);

  //  aHDR->setComputeZMP(true);
  // This is mandatory for this implementation of computeForwardKinematics
  // to compute the derivative of the momentum.
  {
    string inProperty[5]={"TimeStep","ComputeAcceleration",
			  "ComputeBackwardDynamics", "ComputeZMP","ComputeAccelerationCoM"};
    string inValue[5]={"0.005","true","true","true","true"};
    for(unsigned int i=0;i<5;i++)
      aHDR->setProperty(inProperty[i],inValue[i]);

  }

  aHDR->computeForwardKinematics();
  ZMPval = aHDR->zeroMomentumPoint();
  tcout << "First value of ZMP : "
	<< filterprecision(ZMPval(0)) << " "
	<< filterprecision(ZMPval(1)) << " "
	<< filterprecision(ZMPval(2)) << endl;
  MAL_S3_VECTOR(poscom,double);
  poscom = aHDR->positionCenterOfMass();
  tcout << "Should be equal to the CoM: "
	<< filterprecision(poscom(0)) << " "
	<< filterprecision(poscom(1)) << " "
	<< filterprecision(poscom(2)) << endl;

  matrixNxP InertiaMatrix;
  aHDR->computeInertiaMatrix();
  InertiaMatrix = aHDR->inertiaMatrix();

  tcout << "InertiaMatrix("
       << MAL_MATRIX_NB_ROWS(InertiaMatrix)<< ","
       << MAL_MATRIX_NB_COLS(InertiaMatrix)<< ")"<< endl;

  DisplayMatrix(InertiaMatrix,tcout);

  ofstream aof;
  aof.open("InertiaMatrix.dat");
  for(unsigned int i=0;i<MAL_MATRIX_NB_ROWS(InertiaMatrix);i++)
    {
      for(unsigned int j=0;j<MAL_MATRIX_NB_COLS(InertiaMatrix);j++)
       {
         aof << InertiaMatrix(i,j) << " ";
       }
      aof << endl;
    }
  aof.close();

  std::vector<CjrlJoint *> aVec = aHDR->jointVector();

  // Get the Jacobian of the right ankle.
  CjrlJoint  * aJoint = aHDR->rightAnkle();
  aJoint->computeJacobianJointWrtConfig();

  tcout << "Jacobian of the right ankle." << endl;
  MAL_MATRIX(,double) aJ;
  aJ = aJoint->jacobianJointWrtConfig();
  DisplayMatrix(aJ,tcout);

  // Get the articular Jacobian from the right ankle to the right wrist.
  vector3d origin; origin(0) = 0.0; origin(1) = 0.0; origin(2) = 0.0;
  aHDR->getJacobian(*aHDR->rightAnkle(),
		    *aHDR->rightWrist(),
		    origin,
		    aJ);
  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);
  MAL_MATRIX_RESIZE(aJ,3, MAL_MATRIX_NB_COLS(aJ));
  // Get the linear part of the articular Jacobian from the right ankle to the right wrist.
  aHDR->getPositionJacobian(*aHDR->rightAnkle(),
			    *aHDR->rightWrist(),
			    origin,
			    aJ);
  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);

  // Get the angular part of the articular Jacobian from the right ankle to the right wrist.
  aHDR->getOrientationJacobian(*aHDR->rightAnkle(),
			       *aHDR->rightWrist(),
			       aJ);

  tcout << "Jacobian from the right ankle to the right wrist. " << endl;
  DisplayMatrix(aJ,tcout);

  tcout << "****************************" << endl;
  rootJoint->computeJacobianJointWrtConfig();
  aJ = rootJoint->jacobianJointWrtConfig();

  tcout << "Rank of Root: " << rootJoint->rankInConfiguration() << endl;

  //  DisplayMatrix(aJ);

  aJoint = aHDR->waist();
  tcout << "****************************" << endl;
  aHDR->computeJacobianCenterOfMass();
  DisplayMatrix(aHDR->jacobianCenterOfMass(),tcout);
  tcout << "****************************" << endl;
  RecursiveDisplayOfJoints(rootJoint,tcout,10);

  tcout << "****************************" << endl;

  // Test rank of the hands.
  tcout << "Rank of the right hand "<< endl;
  tcout << aHDR->rightWrist()->rankInConfiguration() << endl;
  CjrlHand *rightHand = aHDR->rightHand();
  string empty("");
  DisplayHand(rightHand,empty,tcout);

  tcout << "Rank of the left hand "<< endl;
  tcout << aHDR->leftWrist()->rankInConfiguration() << endl;
  CjrlHand *leftHand = aHDR->leftHand();
  DisplayHand(leftHand,empty,tcout);

  // Test rank of the feet.
  tcout << "Rank of the right foot "<< endl;
  tcout << aHDR->rightFoot()->associatedAnkle()->rankInConfiguration() << endl;
  CjrlFoot *rightFoot = aHDR->rightFoot();
  DisplayFoot(rightFoot,empty,tcout);

  tcout << "Rank of the left foot "<< endl;
  tcout << aHDR->leftFoot()->associatedAnkle()->rankInConfiguration() << endl;
  CjrlFoot *leftFoot = aHDR->leftFoot();
  DisplayFoot(leftFoot,empty,tcout);

  tcout << "Current transformation of left Ankle."<< endl;
  dm4d(aHDR->leftAnkle()->currentTransformation(),tcout,empty);
  tcout << endl;
  tcout << "Current transformation of right Ankle."<< endl;
  dm4d(aHDR->rightAnkle()->currentTransformation(),tcout,empty);
  tcout << endl;

  for(int i=0;i<4;i++)
    {
      aHDR->currentVelocity(aCurrentVel);
      aHDR->currentAcceleration(aCurrentAcc);
      aHDR->computeForwardKinematics();
      ZMPval = aHDR->zeroMomentumPoint();
      tcout << i << "-th value of ZMP : "
	    << filterprecision(ZMPval(0)) << " "
	    << filterprecision(ZMPval(1)) << " "
	    << filterprecision(ZMPval(2)) << endl;
      poscom = aHDR->positionCenterOfMass();
      tcout << "Should be equal to the CoM: "
	    << filterprecision(poscom(0)) << " "
	    << filterprecision(poscom(1)) << " "
	    << filterprecision(poscom(2)) << endl;
    }

  // Check the information on actuated joints.
  std::vector<CjrlJoint *> ActuatedJoints = aHDR->getActuatedJoints();

  tcout << "Size of actuated Joints:" << ActuatedJoints.size() << endl;
  for(unsigned int i=0;i<ActuatedJoints.size();i++)
    tcout << "Rank of actuated joints ("<<i<< ") in configuration :"
	  << ActuatedJoints[i]->rankInConfiguration() << endl;

  tcout << "Humanoid mass:" << aHDR->mass() << endl;

  DisplayForces(aHDR,empty,tcout);
  DisplayTorques(aHDR,empty, tcout);

  // Test torques.
  tcout << "Test Torques:" << endl;
  const matrixNxP& Torques = aHDR->currentTorques();
  for(unsigned int i=6;i<MAL_MATRIX_NB_ROWS(Torques);i++)
    {
      double torquefrominertia = 9.81 * InertiaMatrix(i,2);
      tcout << filterprecision(Torques(i,0)) << " "
	    << filterprecision(torquefrominertia) << " \t DD \t " << Torques(i,0)-torquefrominertia << endl;
    }
  tcout << "Test Linear Velocity:" << endl;
  DisplayLinearVelocity(aHDR,tcout);
  tcout << "Test Angular Velocity:" << endl;
  DisplayAngularVelocity(aHDR,tcout);

  tcout << "Test Linear Acceleration:" << endl;
  DisplayLinearAcceleration(aHDR,tcout);
  tcout << "Test Angular Acceleration:" << endl;
  DisplayAngularAcceleration(aHDR,tcout);

  tcout.close();

  // ASCII Comparison between the generated output and the reference one
  // given in argument.
  if (argc==2)
    {
      char OurFileName[120]="output.txt";
      char ReportFileName[120]="reportthdr.txt";
      if (CompareTwoFiles(argv[1],
			  OurFileName,
			  ReportFileName))
	{
	  delete aHDR;
	  return 0;
	}
    }
  delete aHDR;
  return -1;
}
<|endoftext|>


<commit_before>/*
 * Gratings.cpp
 *
 *  Created on: Oct 23, 2009
 *      Author: travel
 */

#include "Gratings.hpp"
#include <src/include/pv_common.h>  // for PI
namespace PV {

//! A derived Image class

/*!
 * Sets the period is sync with the burst frequency of the Retina.
 * Sets the phase of the gratings (is this designed to work with restarted
 * simulations?)
 */
Gratings::Gratings(const char * name, HyPerCol * hc) :
	Image(name, hc) {
	initialize_data(&loc);

	PVParams * params = hc->parameters();
	float freq = params->value(name, "burstFreq", 40.0);

	period = 25;
	if (freq > 0.0) {
		period = 1000 / freq; // in miliseconds
	}

	float dt = hc->getDeltaTime();

	calcPhase(0.0, dt); // time==0.0 initializes random phase, don't delete
	calcPhase(hc->simulationTime(), dt);

	updateImage(0.0, 0.0);
}

Gratings::~Gratings() {
}

//! Updates the image

/*!
 * REMARKS:
 * 	- We work in the extended frame.
 *	- The data buffer is modulated by a sinusoid with
 *     wavelength kx.
 *	- The phase of this sinusoid is set
 *     by a call to calcPhase(). It stays constant during
 *     a time that equals the burstPeriod.
 *	- Comment on how are negative data values handled!
 *	.
 *
 * NOTES:
 *	- We should make this time longer by modifying
 *        calcPhase().
 *
 *	.
 */
bool Gratings::updateImage(float time, float dt) {
	// extended frame
	const int nx = loc.nx + 2 * loc.nPad;
	const int ny = loc.ny + 2 * loc.nPad;
	const int sx = 1;
	const int sy = sx * nx;

	int marginWidth = loc.nPad;

	const float kx = 2.0 * PI / 4.0; // wavenumber
	const float phi = calcPhase(time, dt);

	for (int iy = 0; iy < ny; iy++) {
		//	   int ix = 6 + marginWidth;
		//      for (int ix = 0; ix < nx; ix++) {
		//         float x = (float) (ix + marginWidth);
		//         data[ix*sx + iy*sy] = sin(kx * x + phi);
		//      }
		for (int ix = 6; ix < nx; ix += 6) {
			data[ix * sx + iy * sy] = 1;
		}

	}

	return true;
}

//! Calculates phase of the gratings

/*!
 * When time is a multiple of period we assign one of four possible phases.
 *
 *
 */

float Gratings::calcPhase(float time, float dt) {
	int iperiod = (int) (period / dt);
	int itime = (int) (time / dt);

	if (itime % iperiod == 0) {
		double p = ((double) rand()) / (double) RAND_MAX;
		if (p < 0.25)
			phase = 0.0 * PI;
		else if (p < 0.50)
			phase = 0.5 * PI;
		else if (p < 0.75)
			phase = 1.0 * PI;
		else
			phase = 1.5 * PI;
	}

	return phase;
}

} // namespace PV
<commit_msg>clearImage method included. It is called each time updateImage is called.<commit_after>/*
 * Gratings.cpp
 *
 *  Created on: Oct 23, 2009
 *      Author: travel
 */

#include "Gratings.hpp"
#include <src/include/pv_common.h>  // for PI
namespace PV {

//! A derived Image class

/*!
 * Sets the period is sync with the burst frequency of the Retina.
 * Sets the phase of the gratings (is this designed to work with restarted
 * simulations?)
 */
Gratings::Gratings(const char * name, HyPerCol * hc) :
	Image(name, hc) {
	initialize_data(&loc);

	PVParams * params = hc->parameters();
	float freq = params->value(name, "burstFreq", 40.0);

	period = 25;
	if (freq > 0.0) {
		period = 1000 / freq; // in miliseconds
	}

	float dt = hc->getDeltaTime();

	calcPhase(0.0, dt); // time==0.0 initializes random phase, don't delete
	calcPhase(hc->simulationTime(), dt);

	updateImage(0.0, 0.0);
}

Gratings::~Gratings() {
}

//! CLEAR IMAGE
/*!
 * sets the data buffer to zero.
 *
 */
int Gratings::clearImage()
{
   // set the data buffer to zero.
   //
   const int N = (loc.nx + 2*loc.nPad) *
                    (loc.ny + 2*loc.nPad) * loc.nBands;
   for(int i=0; i<N;i++){
      data[i] = 0;
   }
   return 0;
}

//! UPDATES IMAGE

/*!
 * REMARKS:
 * 	- We work in the extended frame.
 *	- The data buffer is modulated by a sinusoid with
 *     wavelength kx.
 *	- The phase of this sinusoid is set
 *     by a call to calcPhase(). It stays constant during
 *     a time that equals the burstPeriod.
 *	- Comment on how are negative data values handled!
 *	.
 *
 * NOTES:
 *	- We should increase the time that the phase remain constant
 *	 by modifying calcPhase().
 *
 *	.
 */
bool Gratings::updateImage(float time, float dt) {
	// extended frame
	const int nx = loc.nx + 2 * loc.nPad;
	const int ny = loc.ny + 2 * loc.nPad;
	const int sx = 1;
	const int sy = sx * nx;

	int marginWidth = loc.nPad;

	//const float kx = 2.0 * PI / 4.0; // wavenumber
	//const float phi = calcPhase(time, dt);
	//const float phi = 0.5*PI;
    //double r =  ((double) rand()) / (double) RAND_MAX;
	//int ix = (int) (r * nx);
    //printf("ix = %d\n",ix);

    clearImage();

	for (int iy = 0; iy < ny; iy++) {
			   int ix = 6 + marginWidth;
		     //for (int ix = 0; ix < nx; ix++) {
		       //  float x = (float) (ix + marginWidth);
		         //float x = (float) (ix);
		         //data[ix*sx + iy*sy] = 1 + sin(kx * x + phi);
		      //}
		//for (int ix = 10; ix < nx; ix += 14) {
		//	data[ix * sx + iy * sy] = 1;
		//}
		data[ix * sx + iy * sy] = 1;
	}

	return true;
}

//! Calculates phase of the gratings

/*!
 * When time is a multiple of period we assign one of four possible phases.
 *
 *
 */

float Gratings::calcPhase(float time, float dt) {
	int iperiod = (int) (period / dt);
	int itime = (int) (time / dt);

	if (itime % iperiod == 0) {
		double p = ((double) rand()) / (double) RAND_MAX;
		if (p < 0.25)
			phase = 0.0 * PI;
		else if (p < 0.50)
			phase = 0.5 * PI;
		else if (p < 0.75)
			phase = 1.0 * PI;
		else
			phase = 1.5 * PI;
	}

	return phase;
}

} // namespace PV
<|endoftext|>


<commit_before>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    std::deque<int>::iterator it;
    int greatest = 0;
    int value = 0;
    // pushing all values to the deque
    for (int i = 0; i < n; i++) {
        mydeque.push_front(arr[i]);
    }
    // pushing all the greatest values
    // on each k-elements
    // to the back of the deque

    // cleaning the deque
    while (mydeque.size() > 0)
        mydeque.pop_front();
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<commit_msg>Starts solution for the Deque-STL challenge.<commit_after>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    std::deque<int>::iterator it;
    int greatest = 0;
    int value = 0;
    int index = 0;
    // pushing all values to the deque
    for (int i = 0; i < n; i++) {
        mydeque.push_front(arr[i]);
    }
    // pushing all the greatest values
    // on each k-elements
    // to the back of the deque
    it = mydeque.begin();
    for (int i = 0; i < n-k+1; i++) {
        if (index < k) {
            value = *it;
            if (value > greatest)
                greatest = value;
            if (index == k - 1) {
                mydeque.push_back(greatest);
                greatest = 0;
            }
            index++;
        } else {
            index = 0;
        }
    }

    for (int i = 0; i < n-k+1; i++) {
        cout << mydeque.back() << " ";
        mydeque.pop_back();
    }
    cout << endl;

    // cleaning the deque
    while (mydeque.size() > 0)
        mydeque.pop_front();
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  L3 Magnet                                                                //
//                                                                           //
//Begin_Html
/*

The responsible person for this module is
Andreas Morsch.

*/
//End_Html
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <TVirtualMC.h>

#include "AliMAG.h"
#include "AliMagF.h"
#include "AliRun.h"

ClassImp(AliMAG)

//_____________________________________________________________________________
AliMAG::AliMAG()
{
  //
  // Default constructor for L3 magnet
  //
}

//_____________________________________________________________________________
AliMAG::AliMAG(const char *name, const char *title)
  : AliModule(name,title)
{
  //
  // Standard constructor for L3 magnet
  //
  //Begin_Html
  /*

  */
  //End_Html

  SetMarkerColor(7);
  SetMarkerStyle(2);
  SetMarkerSize(0.4);
}

//_____________________________________________________________________________
void AliMAG::CreateGeometry()
{
  //
  // Create geometry for L3 magnet
  //
  //Begin_Html
  /*

  */
  //End_Html
  //Begin_Html
  /*

  */
  //End_Html

  Int_t *idtmed = fIdtmed->GetArray()-299;

  Float_t dpar[13];
  Int_t idrotm[399];
  Float_t par[10];

  // ANGLE POLAIRE MAXIMUM

  //  Define Mother

  par[0] = 22.5;
  par[1] = 360.;
  par[2] = 8.;
  par[3] = 2.;
  par[4] = -600.;
  par[5] = 580.;
  par[6] = 790.;
  par[7] = 600.;
  par[8] = 580.;
  par[9] = 790.;
  gMC->Gsvolu("L3MO", "PGON", idtmed[334], par, 10);
  gMC->Gspos("L3MO", 1, "ALIC", 0., -30., 0., 0, "ONLY");

  // Define coils

  par[5] = 585.;
  par[6] = 690.;
  par[8] = 585.;
  par[9] = 690.;
  gMC->Gsvolu("L3CO", "PGON", idtmed[328], par, 10);
  gMC->Gspos("L3CO", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  par[5] = 580.;
  par[6] = 585.;
  par[8] = 580.;
  par[9] = 585.;
  gMC->Gsvolu("L3C1", "PGON", idtmed[308], par, 10);
  gMC->Gspos("L3C1", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  // Define yoke

  par[5] = 690.;
  par[6] = 790.;
  par[8] = 690.;
  par[9] = 790.;
  gMC->Gsvolu("L3YO", "PGON", idtmed[329], par, 10);
  gMC->Gspos("L3YO", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  // Define the return yoke of L3 (DOOR)

  par[4] = 600.;
  par[5] = 0.;
  par[6] = 790.;
  par[7] = 700.;
  par[8] = par[5];
  par[9] = par[6];
  gMC->Gsvolu("L3DO", "PGON", idtmed[334], par, 10);
  gMC->Gsvolu("L3DX", "PGON", idtmed[334], par, 10);

  par[4] = 610.;
  par[5] = 0.;
  par[6] = 790.;
  par[7] = 700.;
  par[8] = par[5];
  par[9] = par[6];
  gMC->Gsvolu("L3FR", "PGON", idtmed[329], par, 10);
  gMC->Gsvolu("L3FX", "PGON", idtmed[329], par, 10);

  // INNER LAYER

  par[4] = 600.;
  par[7] = 610.;
  gMC->Gsvolu("L3IR", "PGON", idtmed[309], par, 10);
  gMC->Gsvolu("L3IX", "PGON", idtmed[309], par, 10);

  //     DOOR OPENING

  dpar[0] = 22.5;
  dpar[1] = 360;
  dpar[2] = 8.;
  dpar[3] = 3.;
  dpar[4] = 610.;
  dpar[5] = 0.;
  dpar[6] = 163.5;
  dpar[7] = 670.;
  dpar[8] = dpar[5];
  dpar[9] = dpar[6];
  dpar[10] = 700.;
  dpar[11] = dpar[5];
  dpar[12] = dpar[6] + 50.;
  gMC->Gsvolu("L3O1", "PGON", idtmed[314], dpar, 13);
  gMC->Gsvolu("L3O3", "PGON", idtmed[314], dpar, 13);
  par[4] = 600.;
  par[5] = 0.;
  par[6] = 163.5;
  par[7] = 610.;
  par[8] = 0.;
  par[9] = 163.5;
  gMC->Gsvolu("L3O2", "PGON", idtmed[314], par, 10);
  gMC->Gsvolu("L3O4", "PGON", idtmed[314], par, 10);

  //     THE DOOR OPENING HAS TO BE PLACED WITH 'MANY' SINCE THE REGION
  //     WILL CONTAIN A MUON CHAMBER, BEAM PIPE AND BEAM SHIELD
  //     PLACED WITH 'ONLY'.

  AliMatrix(idrotm[300], 90., 0., 90., 90., 180., 0.);

  gMC->Gspos("L3DO", 1, "ALIC", 0., -30., 0., 0, "MANY");
  gMC->Gspos("L3FR", 1, "L3DO", 0., 0., 0., 0, "MANY");
  gMC->Gspos("L3IR", 1, "L3DO", 0., 0., 0., 0, "MANY");

  gMC->Gspos("L3DX", 1, "ALIC", 0., -30., 0., idrotm[300], "MANY");
  gMC->Gspos("L3FX", 1, "L3DX", 0., 0., 0., 0, "MANY");
  gMC->Gspos("L3IX", 1, "L3DX", 0., 0., 0., 0, "MANY");

  if(!strcmp(gMC->GetName(),"TGeant3") || !strcmp(gMC->GetName(),"TFluka")) {

    gMC->Gspos("L3O1", 1, "L3FR", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O2", 1, "L3IR", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O3", 1, "L3FX", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O4", 1, "L3IX", 0., 30., 0., 0, "MANY");

  }
  else {
    gMC->Gspos("L3O1", 1, "ALIC", 0., 0., 0., 0, "MANY");
    gMC->Gspos("L3O2", 1, "ALIC", 0., 0., 0., 0, "MANY");
    gMC->Gsbool("L3O1", "L3DO");
    gMC->Gsbool("L3O2", "L3DO");

    gMC->Gspos("L3O3", 1, "ALIC", 0., 0., 0., idrotm[300], "MANY");
    gMC->Gspos("L3O4", 1, "ALIC", 0., 0., 0., idrotm[300], "MANY");
    gMC->Gsbool("L3O3", "L3DX");
    gMC->Gsbool("L3O4", "L3DX");
  }
}

//_____________________________________________________________________________
void AliMAG::CreateMaterials()
{
  //
  // Create materials for L3 magnet
  //

  Int_t   isxfld = gAlice->Field()->Integ();
  Float_t sxmgmx = gAlice->Field()->Max();
  Float_t epsil, stmin, deemax, tmaxfd, stemax;

  // --- Define the various materials for GEANT ---

  Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
  Float_t zAir[4]={6.,7.,8.,18.};
  Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
  Float_t dAir = 1.20479E-3;

  //     Aluminum
  AliMaterial(9, "Al0$", 26.98, 13., 2.7, 8.9, 37.2);
  AliMaterial(29, "Al1$", 26.98, 13., 2.7, 8.9, 37.2);

  //     Iron
  AliMaterial(10, "Fe0$", 55.85, 26., 7.87, 1.76, 17.1);
  AliMaterial(30, "Fe1$", 55.85, 26., 7.87, 1.76, 17.1);

  //     Air
  AliMixture(15, "AIR0$      ", aAir, zAir, dAir, 4, wAir);
  AliMixture(35, "AIR1$      ", aAir, zAir, dAir, 4, wAir);

  // ****************
  //     Defines tracking media parameters.
  //     Les valeurs sont commentees pour laisser le defaut
  //     a GEANT (version 3-21, page CONS200), f.m.
  epsil  = .001;  // Tracking precision,
  stemax = -1.;   // Maximum displacement for multiple scat
  tmaxfd = -20.;  // Maximum angle due to field deflection
  deemax = -.3;   // Maximum fractional energy loss, DLS
  stmin  = -.8;
  // ***************

  //    IRON

  AliMedium(10, "FE_C0             ", 10, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(30, "FE_C1             ", 30, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);

  //     ALUMINUM

  AliMedium(9, "ALU_C0            ",  9, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(29, "ALU_C1            ", 29, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);

  //     AIR

  AliMedium(15, "AIR_C0            ", 15, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(35, "AIR_C1            ", 35, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
}

//_____________________________________________________________________________
void AliMAG::DrawModule() const
{
  //
  // Draw a shaded view of the L3 magnet
  //
}

//_____________________________________________________________________________
void AliMAG::Init()
{
  //
  // Initialise L3 magnet after it has been built
  Int_t i;
  //
  if(AliLog::GetGlobalDebugLevel()>0) {
    printf("\n%s: ",ClassName());
    for(i=0;i<35;i++) printf("*");
    printf(" MAG_INIT ");
    for(i=0;i<35;i++) printf("*");
    printf("\n%s: ",ClassName());
    //
    // Here the MAG initialisation code (if any!)
    for(i=0;i<80;i++) printf("*");
    printf("\n");
  }
}

<commit_msg>Constructing AliMAG geometry in the same way with TGeant3, TFluka, and TGeant3TGeo<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  L3 Magnet                                                                //
//                                                                           //
//Begin_Html
/*

The responsible person for this module is
Andreas Morsch.

*/
//End_Html
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <TVirtualMC.h>

#include "AliMAG.h"
#include "AliMagF.h"
#include "AliRun.h"

ClassImp(AliMAG)

//_____________________________________________________________________________
AliMAG::AliMAG()
{
  //
  // Default constructor for L3 magnet
  //
}

//_____________________________________________________________________________
AliMAG::AliMAG(const char *name, const char *title)
  : AliModule(name,title)
{
  //
  // Standard constructor for L3 magnet
  //
  //Begin_Html
  /*

  */
  //End_Html

  SetMarkerColor(7);
  SetMarkerStyle(2);
  SetMarkerSize(0.4);
}

//_____________________________________________________________________________
void AliMAG::CreateGeometry()
{
  //
  // Create geometry for L3 magnet
  //
  //Begin_Html
  /*

  */
  //End_Html
  //Begin_Html
  /*

  */
  //End_Html

  Int_t *idtmed = fIdtmed->GetArray()-299;

  Float_t dpar[13];
  Int_t idrotm[399];
  Float_t par[10];

  // ANGLE POLAIRE MAXIMUM

  //  Define Mother

  par[0] = 22.5;
  par[1] = 360.;
  par[2] = 8.;
  par[3] = 2.;
  par[4] = -600.;
  par[5] = 580.;
  par[6] = 790.;
  par[7] = 600.;
  par[8] = 580.;
  par[9] = 790.;
  gMC->Gsvolu("L3MO", "PGON", idtmed[334], par, 10);
  gMC->Gspos("L3MO", 1, "ALIC", 0., -30., 0., 0, "ONLY");

  // Define coils

  par[5] = 585.;
  par[6] = 690.;
  par[8] = 585.;
  par[9] = 690.;
  gMC->Gsvolu("L3CO", "PGON", idtmed[328], par, 10);
  gMC->Gspos("L3CO", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  par[5] = 580.;
  par[6] = 585.;
  par[8] = 580.;
  par[9] = 585.;
  gMC->Gsvolu("L3C1", "PGON", idtmed[308], par, 10);
  gMC->Gspos("L3C1", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  // Define yoke

  par[5] = 690.;
  par[6] = 790.;
  par[8] = 690.;
  par[9] = 790.;
  gMC->Gsvolu("L3YO", "PGON", idtmed[329], par, 10);
  gMC->Gspos("L3YO", 1, "L3MO", 0., 0., 0., 0, "ONLY");

  // Define the return yoke of L3 (DOOR)

  par[4] = 600.;
  par[5] = 0.;
  par[6] = 790.;
  par[7] = 700.;
  par[8] = par[5];
  par[9] = par[6];
  gMC->Gsvolu("L3DO", "PGON", idtmed[334], par, 10);
  gMC->Gsvolu("L3DX", "PGON", idtmed[334], par, 10);

  par[4] = 610.;
  par[5] = 0.;
  par[6] = 790.;
  par[7] = 700.;
  par[8] = par[5];
  par[9] = par[6];
  gMC->Gsvolu("L3FR", "PGON", idtmed[329], par, 10);
  gMC->Gsvolu("L3FX", "PGON", idtmed[329], par, 10);

  // INNER LAYER

  par[4] = 600.;
  par[7] = 610.;
  gMC->Gsvolu("L3IR", "PGON", idtmed[309], par, 10);
  gMC->Gsvolu("L3IX", "PGON", idtmed[309], par, 10);

  //     DOOR OPENING

  dpar[0] = 22.5;
  dpar[1] = 360;
  dpar[2] = 8.;
  dpar[3] = 3.;
  dpar[4] = 610.;
  dpar[5] = 0.;
  dpar[6] = 163.5;
  dpar[7] = 670.;
  dpar[8] = dpar[5];
  dpar[9] = dpar[6];
  dpar[10] = 700.;
  dpar[11] = dpar[5];
  dpar[12] = dpar[6] + 50.;
  gMC->Gsvolu("L3O1", "PGON", idtmed[314], dpar, 13);
  gMC->Gsvolu("L3O3", "PGON", idtmed[314], dpar, 13);
  par[4] = 600.;
  par[5] = 0.;
  par[6] = 163.5;
  par[7] = 610.;
  par[8] = 0.;
  par[9] = 163.5;
  gMC->Gsvolu("L3O2", "PGON", idtmed[314], par, 10);
  gMC->Gsvolu("L3O4", "PGON", idtmed[314], par, 10);

  //     THE DOOR OPENING HAS TO BE PLACED WITH 'MANY' SINCE THE REGION
  //     WILL CONTAIN A MUON CHAMBER, BEAM PIPE AND BEAM SHIELD
  //     PLACED WITH 'ONLY'.

  AliMatrix(idrotm[300], 90., 0., 90., 90., 180., 0.);

  gMC->Gspos("L3DO", 1, "ALIC", 0., -30., 0., 0, "MANY");
  gMC->Gspos("L3FR", 1, "L3DO", 0., 0., 0., 0, "MANY");
  gMC->Gspos("L3IR", 1, "L3DO", 0., 0., 0., 0, "MANY");

  gMC->Gspos("L3DX", 1, "ALIC", 0., -30., 0., idrotm[300], "MANY");
  gMC->Gspos("L3FX", 1, "L3DX", 0., 0., 0., 0, "MANY");
  gMC->Gspos("L3IX", 1, "L3DX", 0., 0., 0., 0, "MANY");

  if(!strcmp(gMC->GetName(),"TGeant3")
     || !strcmp(gMC->GetName(),"TFluka")
     || !strcmp(gMC->GetName(),"TGeant3TGeo")) {

    gMC->Gspos("L3O1", 1, "L3FR", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O2", 1, "L3IR", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O3", 1, "L3FX", 0., 30., 0., 0, "MANY");
    gMC->Gspos("L3O4", 1, "L3IX", 0., 30., 0., 0, "MANY");

  }
  else {
    gMC->Gspos("L3O1", 1, "ALIC", 0., 0., 0., 0, "MANY");
    gMC->Gspos("L3O2", 1, "ALIC", 0., 0., 0., 0, "MANY");
    gMC->Gsbool("L3O1", "L3DO");
    gMC->Gsbool("L3O2", "L3DO");

    gMC->Gspos("L3O3", 1, "ALIC", 0., 0., 0., idrotm[300], "MANY");
    gMC->Gspos("L3O4", 1, "ALIC", 0., 0., 0., idrotm[300], "MANY");
    gMC->Gsbool("L3O3", "L3DX");
    gMC->Gsbool("L3O4", "L3DX");
  }
}

//_____________________________________________________________________________
void AliMAG::CreateMaterials()
{
  //
  // Create materials for L3 magnet
  //

  Int_t   isxfld = gAlice->Field()->Integ();
  Float_t sxmgmx = gAlice->Field()->Max();
  Float_t epsil, stmin, deemax, tmaxfd, stemax;

  // --- Define the various materials for GEANT ---

  Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
  Float_t zAir[4]={6.,7.,8.,18.};
  Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
  Float_t dAir = 1.20479E-3;

  //     Aluminum
  AliMaterial(9, "Al0$", 26.98, 13., 2.7, 8.9, 37.2);
  AliMaterial(29, "Al1$", 26.98, 13., 2.7, 8.9, 37.2);

  //     Iron
  AliMaterial(10, "Fe0$", 55.85, 26., 7.87, 1.76, 17.1);
  AliMaterial(30, "Fe1$", 55.85, 26., 7.87, 1.76, 17.1);

  //     Air
  AliMixture(15, "AIR0$      ", aAir, zAir, dAir, 4, wAir);
  AliMixture(35, "AIR1$      ", aAir, zAir, dAir, 4, wAir);

  // ****************
  //     Defines tracking media parameters.
  //     Les valeurs sont commentees pour laisser le defaut
  //     a GEANT (version 3-21, page CONS200), f.m.
  epsil  = .001;  // Tracking precision,
  stemax = -1.;   // Maximum displacement for multiple scat
  tmaxfd = -20.;  // Maximum angle due to field deflection
  deemax = -.3;   // Maximum fractional energy loss, DLS
  stmin  = -.8;
  // ***************

  //    IRON

  AliMedium(10, "FE_C0             ", 10, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(30, "FE_C1             ", 30, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);

  //     ALUMINUM

  AliMedium(9, "ALU_C0            ",  9, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(29, "ALU_C1            ", 29, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);

  //     AIR

  AliMedium(15, "AIR_C0            ", 15, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
  AliMedium(35, "AIR_C1            ", 35, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
}

//_____________________________________________________________________________
void AliMAG::DrawModule() const
{
  //
  // Draw a shaded view of the L3 magnet
  //
}

//_____________________________________________________________________________
void AliMAG::Init()
{
  //
  // Initialise L3 magnet after it has been built
  Int_t i;
  //
  if(AliLog::GetGlobalDebugLevel()>0) {
    printf("\n%s: ",ClassName());
    for(i=0;i<35;i++) printf("*");
    printf(" MAG_INIT ");
    for(i=0;i<35;i++) printf("*");
    printf("\n%s: ",ClassName());
    //
    // Here the MAG initialisation code (if any!)
    for(i=0;i<80;i++) printf("*");
    printf("\n");
  }
}

<|endoftext|>