/* ======================================================================== *\
!
! *
! * 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): Christoph Kolodziejski, 12/2004  <mailto:>
!   Author(s): Thomas Bretz, 12/2004  <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2004-2005
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MGeomCamMagicXT
//
// This class stores the geometry information of the 'extended' Magic
// camera. The extended geometry has also small pixels in the outer region.
// To convert MCerPhotEvt from MGeomCamMagic to MGeomCamMagicXT use
// MGeomCamMagicExtend.
//
////////////////////////////////////////////////////////////////////////////
#include "MGeomCamMagicXT.h"

#include "MGeomPix.h"

ClassImp(MGeomCamMagicXT);

// --------------------------------------------------------------------------
//
//  Magic camera has 577 pixels. For geometry and Next Neighbor info see
//  CreateCam and CreateNN
//
MGeomCamMagicXT::MGeomCamMagicXT(const char *name)
    : MGeomCam(1141, 17, name, "Geometry information of Magic Camera")
{
    CreateCam();
    CreateNN();
    InitGeometry();
}

// --------------------------------------------------------------------------
//
//  This fills the geometry information from a table into the pixel objects.
//
void MGeomCamMagicXT::CreateCam()
{
    //
    // fill the geometry class with the coordinates of the CT1 camera
    //
    //*fLog << inf << " Create CT1 geometry " << endl;

    //
    // this algorithm is from Martin Kestel originally
    // it was punt into a root/C++ context by Harald Kornmayer and Thomas Bretz
   
    const Float_t diameter = 30;    // units are mm
    const Float_t kS32  = sqrt(3)/2;

    //
    //  add the first pixel to the list
    //
    Int_t pixnum = 0;

    (*this)[pixnum++].Set(0, 0, diameter);

    for (Int_t ring=1; ring<20; ring++)
    {
        //
        // calc. coords for this ring counting from the
        // starting number to the ending number
        //
        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set((ring-i*0.5)*diameter,
                                  i*kS32*diameter,
                                  diameter);

        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set((ring*0.5-i)*diameter,
                                  ring*kS32 * diameter,
                                  diameter);

        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set(-(ring+i)*0.5*diameter,
                                  (ring-i)*kS32*diameter,
                                  diameter);

        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set((0.5*i-ring)*diameter,
                                  -i*kS32*diameter,
                                  diameter);

        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set((i-ring*0.5)*diameter,
                                  -ring*kS32 * diameter,
                                  diameter);

        for (int i=0; i<ring; i++)
            (*this)[pixnum++].Set((ring+i)*0.5*diameter,
                                  (-ring+i)*kS32*diameter,
                                  diameter);
    }
}

// --------------------------------------------------------------------------
//
//  This fills the next neighbor information from a table into the pixel
//  objects.
//
void MGeomCamMagicXT::CreateNN()
{
    Int_t pos = 0;

    const Short_t nn[7][6] = {         // Neighbors of #
        {   1,   2,   3,   4,   5,   6}, // 0
        {   0,   2,   6,   7,   8,  18},
        {   0,   1,   3,   8,   9,  10},
        {   0,   2,   4,  10,  11,  12},
        {   0,   3,   5,  12,  13,  14},
        {   0,   4,   6,  14,  15,  16},
        {   0,   1,   5,  16,  17,  18}
    };

    for (Int_t i=0; i<7; i++)
        (*this)[pos++].SetNeighbors(nn[i][0], nn[i][1], nn[i][2],
                                    nn[i][3], nn[i][4], nn[i][5]);

    for (Int_t ring=2; ring<20; ring++)
    {
        for (Int_t s=0; s<6; s++)
        {
            for (int i=pos; i<ring+pos; i++)
            {
                Int_t n[6], idx[6];

                n[0] = i==pos&&s==0 ? i+6*ring : i-1;                // vor
                n[1] = i==ring+pos-1&&s==5 ? i-12*(ring-1)-5 : i+1;  // danach
                n[2] = i==pos ? i+6*ring-1+s   : i-6*(ring-1)-s;     // ring- groesser
                n[3] = i==pos ? i-6*(ring-1)-s : i-6*(ring-1)-1-s;   // ring- kleiner
                n[4] = i==pos&&s==0 ? i+12*ring+5 : i+6*ring+s;      // ring+ kleiner
                n[5] = i+6*ring+1+s;                                 // ring+ groesser

                if (n[0]>1140)
                    n[0] = -1;
                if (n[1]>1140)
                    n[1] = -1;
                if (n[2]>1140)
                    n[2] = -1;
                if (n[3]>1140)
                    n[3] = -1;
                if (n[4]>1140)
                    n[4] = -1;
                if (n[5]>1140)
                    n[5] = -1;

                TMath::Sort(6, n, idx);

                (*this)[i].SetNeighbors(n[idx[0]],
                                        n[idx[1]],
                                        n[idx[2]],
                                        n[idx[3]],
                                        n[idx[4]],
                                        n[idx[5]]);
            }

            pos += ring;
        }
    }
}
