/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz, 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
!   Author(s): Harald Kornmayer 1/2001
!
!   Copyright: MAGIC Software Development, 2000-2003
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
// MGeomPix
//
// This container stores the geometry (position) information of
// a single pixel together with the information about next neighbors.
//
// The BIT(22) and BIT(23) is used to flag the pixels in the outer
// and outermost ring. Please don't use this bits in conjuction with
// MGeomPix.
//
//
// Version 1:
// ----------
//  - first implementation
//
// Version 2:
// ----------
//  - added fA
//
// Version 3:
// ----------
//  - added fAidx
//
//
// FIXME: According to an agreement we have to change the name 'Id' to 'idx'
//
////////////////////////////////////////////////////////////////////////////
#include "MGeomPix.h"

#include <math.h>

#include "MLog.h"
#include "MLogManip.h"

#include "MGeomCam.h"

ClassImp(MGeomPix);

using namespace std;

const Float_t MGeomPix::gsTan30 = tan(30/kRad2Deg);
const Float_t MGeomPix::gsTan60 = tan(60/kRad2Deg);

// --------------------------------------------------------------------------
//
// Initializes one pixel
//
MGeomPix::MGeomPix(Float_t x, Float_t y, Float_t r, UInt_t s, UInt_t a)
{
    //  default constructor
    Set(x, y, r, s, a);
}

// --------------------------------------------------------------------------
//
// Initializes Next Neighbors.
//
// WARNING: This function is public, but it is not meant for user access.
// It should only be used from geometry classes (like MGeomCam)
//
void MGeomPix::SetNeighbors(Short_t i0, Short_t i1, Short_t i2,
                            Short_t i3, Short_t i4, Short_t i5)
{
    fNeighbors[0] = i0;
    fNeighbors[1] = i1;
    fNeighbors[2] = i2;
    fNeighbors[3] = i3;
    fNeighbors[4] = i4;
    fNeighbors[5] = i5;

    int i;
    for (i=0; i<6; i++)
        if (fNeighbors[i]<0)
            break;

    fNumNeighbors = i;

    if (fNumNeighbors<5)
        SetBit(kIsInOutermostRing);
}

// --------------------------------------------------------------------------
//
//  Set the kIsOuterRing flag if this pixel has a outermost pixel
//  as Next Neighbor and don't have the kIsOutermostRing flag itself.
//
void MGeomPix::CheckOuterRing(const MGeomCam &cam)
{
    if (IsInOutermostRing())
        return;

    for (int i=0; i<fNumNeighbors; i++)
        if (cam[fNeighbors[i]].IsInOutermostRing())
        {
            SetBit(kIsInOuterRing);
            return;
        }
}

// --------------------------------------------------------------------------
//
// Print the geometry information of one pixel.
//
void MGeomPix::Print(Option_t *opt) const
{ 
    //   information about a pixel
    *fLog << all << "MPixGeom:  x= " << fX << "mm  y= " << fY << "mm ";
    *fLog << "d= " << fD << "mm  A= " << fA << "mm˛" << endl;
}

// ------------------------------------------------------------------------
//
// compute the distance of a point (px,py) to the Hexagon center in
// MGeomPix coordinates. Return kTRUE if inside.
//
Bool_t MGeomPix::IsInside(Float_t px, Float_t py) const
{
    //
    //  compute the distance of the Point to the center of the Hexagon
    //
    const Double_t dx = px-fX;

    //
    // Now check if point is outside of hexagon; just check x coordinate
    // in three coordinate systems: the default one, in which two sides of
    // the hexagon are paralel to the y axis (see camera displays) and two 
    // more, rotated with respect to that one by +- 60 degrees.
    //
    if (TMath::Abs(dx)*2>fD)
        return kFALSE;

    const Double_t dy = py-fY;

    const static Double_t cos60 = TMath::Cos(60/kRad2Deg);
    const static Double_t sin60 = TMath::Sin(60/kRad2Deg);

    const Double_t dx2 = dx*cos60 + dy*sin60;
    if  (TMath::Abs(dx2)*2>fD)
        return kFALSE;

    const Double_t dx3 = dx*cos60 - dy*sin60;
    if (TMath::Abs(dx3)*2>fD)
        return kFALSE;

    return kTRUE;
}
