/*
 * class MirrorPosition
 *
 * $Date$
 * $Revision$
 *
 */

#ifndef MIRROR_POSITION_HH__
#define MIRROR_POSITION_HH__

#include "Wave/VectorPosition.hh"

/** 
 * @addtogroup Wave 
 * @{ */

/** 
 * A Mirror index (abstract). Performs symmetric, periodic and whatever
 * extensions to a vector or a part of it.
 */
/*abstract*/
class 
MirrorPosition: public VectorPosition
{
public:
  /** Constructor. Allows to specify nonstandard symmetry details.
   * @param laxis
   * an additional mirroring axis is used on the left side, like
   * 3-2-1-0-|-0-1-2-3
   * @param raxis
   * an additional mirroring axis is used on the right side, like
   * 3-2-1-0-|-0-1-2-3 */
  MirrorPosition (bool laxis = false, bool raxis = false);
  
  /** Constructor. Calls the superclass' constructor. */
  MirrorPosition (int newsize) : VectorPosition (newsize) 
  { m_leftaxis = m_rightaxis = false; } 
  
  /** Calculate real position assuming a given vector start and length. 
   * If a position is greater than the assumed size or less than the 
   * assumed start position we mirror the position back into range.
   * @param position
   * the requested position
   * @param start
   * the assumed start
   * @param end
   * the assumed end point
   * @param sign
   * -1 if {\em symmetry} is set and we're in the first half of
   * a period, else 1
   * @return
   * the new position */
  int pos (int position, int start, int end, int &sign);

  /** Set left mirroring axis.
   * @param laxis
   * an additional mirroring axis is used on the left side, like
   * 3-2-1-0-|-0-1-2-3 */
  inline void setlaxis (bool laxis) { m_leftaxis = laxis; }

  /** Set right mirroring axis.
   * @param raxis
   * an additional mirroring axis is used on the reft side, like
   * 0-1-2-3-|-3-2-1-0 */
  inline void setraxis (bool raxis) { m_rightaxis = raxis; }

  /** Return the left side axis settings.
   * @return 
   * if an invisible axis exists: {\em true} else {\em false} */
  inline bool laxis (void) { return m_leftaxis; }
  /** Return the right side axis settings.
   * @return 
   * if an invisible axis exists: {\em true} else {\em false} */
  inline bool raxis (void) { return m_rightaxis; }
  
private:
  /** Invisible left axis for mirroring? */
  bool m_leftaxis;
  /** Invisible right axis for mirroring? */
  bool m_rightaxis;
  /** Mirroring with the outer elements as axis on both sides.
   * @param position
   * the requested position
   * @param start
   * the assumed start
   * @param length
   * the assumed length
   * @param sign
   * -1 if {\em m_symmetry} is set and we're in the first half of
   * a period, else 1
   * @return
   * the new position */
  int noaxis (int position, int start, int length, int &sign);
  /** Mirroring with invisible axis on both sides.
   * @param position
   * the requested position
   * @param start
   * the assumed start
   * @param length
   * the assumed length
   * @param sign
   * -1 if {\em m_symmetry} is set and we're in the first half of
   * a period, else 1
   * @return
   * the new position */
  int twoaxis (int position, int start, int length, int &sign);
  /** Mirroring with invisible axis on the left, but none on the right
   * side.
   * @param position
   * the requested position
   * @param start
   * the assumed start
   * @param length
   * the assumed length
   * @param sign
   * -1 if {\em m_symmetry} is set and we're in the first half of
   * a period, else 1
   * @return
   * the new position */
  int oneleftaxis (int position, int start, int length, int &sign);
  /** Mirroring with invisible axis on the right, but none on the left
   * side.
   * @param position
   * the requested position
   * @param start
   * the assumed start
   * @param length
   * the assumed length
   * @param sign
   * -1 if {\em m_symmetry} is set and we're in the first half of
   * a period, else 1
   * @return
   * the new position */
  int onerightaxis (int position, int start, int length, int &sign);
  
}; /* class MirrorPosition */

/** @} */

#endif /* MIRROR_POSITION_HH__ */

