Index: trunk/MagicSoft/Mars/mastro/MAstroCamera.cc
===================================================================
--- trunk/MagicSoft/Mars/mastro/MAstroCamera.cc	(revision 3457)
+++ trunk/MagicSoft/Mars/mastro/MAstroCamera.cc	(revision 3457)
@@ -0,0 +1,316 @@
+/* ======================================================================== *\
+!
+! *
+! * 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, 3/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2004
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MAstroCamera
+//
+// A tools displaying stars from a catalog in the camera display.
+//
+// For a usage example see macros/starfield.C
+//
+// PRELIMINARY!!
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MAstroCamera.h"
+
+#include <KeySymbols.h>
+
+#include <TH2.h>
+#include <TMarker.h>
+#include <TVirtualPad.h>
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MGeomCam.h"
+#include "MGeomMirror.h"
+
+#include "MTime.h"
+#include "../mhist/MHCamera.h"
+#include "MObservatory.h"
+
+ClassImp(MAstroCamera);
+
+using namespace std;
+
+MAstroCamera::MAstroCamera() : fGeom(0), fMirrors(0)
+{
+    fMirror0 = new MGeomMirror;
+    fMirror0->SetMirrorContent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+}
+
+MAstroCamera::~MAstroCamera()
+{
+    if (fGeom)
+        delete fGeom;
+    if (fMirrors)
+        delete fMirrors;
+
+    delete fMirror0;
+}
+
+void MAstroCamera::SetMirrors(TClonesArray *arr)
+{
+    if (!arr || arr->GetClass()!=MGeomMirror::Class())
+        return;
+
+    const Int_t n = arr->GetSize();
+
+    if (!fMirrors)
+        fMirrors = new TClonesArray(MGeomMirror::Class(), n);
+
+    fMirrors->ExpandCreate(n);
+
+    for (int i=0; i<n; i++)
+        memcpy((*fMirrors)[i], (*arr)[i], sizeof(MGeomMirror));
+
+}
+
+void MAstroCamera::SetGeom(const MGeomCam &cam)
+{
+    if (fGeom)
+        delete fGeom;
+
+    fGeom = (MGeomCam*)cam.Clone();
+}
+
+Int_t MAstroCamera::Convert(const TRotation &rot, TVector2 &v, Int_t type)
+{
+    MVector3 w;
+
+    switch (type)
+    {
+    case 1:
+        w.SetRaDec(v.X(), v.Y(), 1);
+        w = w.GetZdAz(*fTime, *fObservatory);
+        break;
+    case 2:
+        w.SetZdAz(v.Y(), v.X(), 1);
+        break;
+    default:
+        return kFALSE;
+    }
+
+    w *= rot;
+
+    const TVector3 spot = fMirror0->GetReflection(w, fGeom->GetCameraDist())*1000;
+
+    /*
+     --- Use this to plot the 'mean grid' instead of the grid of a
+         theoretical central mirror ---
+
+        TVector3 spot;
+        const Int_t num = fConfig->GetNumMirror();
+        for (int i=0; i<num; i++)
+        spot += fConfig->GetMirror(i).GetReflection(w, fGeom->GetCameraDist())*1000;
+        spot *= 1./num;
+        */
+
+    v.Set(spot(1), spot(0));
+
+    const Float_t max = fGeom->GetMaxRadius()*0.70;
+    return v.X()>-max && v.Y()>-max && v.X()<max && v.Y()<max;
+}
+
+void MAstroCamera::DrawNet(const TRotation &rot)
+{
+    TVector2 radec(fRaDec.Phi(), TMath::Pi()/2-fRaDec.Theta());
+    MAstroCatalog::DrawNet(radec, rot, 1);
+
+    const TVector3 zdaz0 = fRaDec.GetZdAz(*fTime, *fObservatory);
+    TVector2 zdaz(zdaz0.Phi(), zdaz0.Theta());
+    MAstroCatalog::DrawNet(zdaz, rot, 2);
+}
+
+TObject *FindObjectInPad(const char *name, TVirtualPad *pad)
+{
+    if (!pad)
+        pad = gPad;
+
+    if (!pad)
+        return NULL;
+
+    TObject *o;
+
+    TIter Next(pad->GetListOfPrimitives());
+    while ((o=Next()))
+    {
+        if (o->InheritsFrom(gROOT->GetClass(name)))
+            return o;
+
+        if (o->InheritsFrom("TPad"))
+            if ((o = FindObjectInPad(name, (TVirtualPad*)o)))
+                return o;
+    }
+    return NULL;
+}
+
+void MAstroCamera::AddPrimitives(Option_t *o)
+{
+    if (!fTime || !fObservatory || !fMirrors)
+    {
+        cout << "Missing data..." << endl;
+        return;
+    }
+
+    TString opt(o);
+    if (opt.IsNull())
+        opt = "*.";
+
+    const Bool_t hashist = opt.Contains("h", TString::kIgnoreCase);
+    const Bool_t hasmean = opt.Contains("*", TString::kIgnoreCase);
+    const Bool_t hasdot  = opt.Contains(".", TString::kIgnoreCase);
+    const Bool_t usecam  = opt.Contains("c", TString::kIgnoreCase);
+
+    TString str = fTime->GetSqlDateTime();
+    str += Form("  (\\alpha=%.1fh \\delta=%.1f\\circ)",
+                fRaDec.Phi()*TMath::RadToDeg()*24/360,
+                90-fRaDec.Theta()*TMath::RadToDeg());
+
+    // Get camera
+    MHCamera *camera=(MHCamera*)FindObjectInPad("MHCamera", gPad);
+    if (camera)
+    {
+        if (!camera->GetGeometry() || camera->GetGeometry()->IsA()!=fGeom->IsA())
+            camera->SetGeometry(*fGeom);
+    }
+    else
+    {
+        camera = new MHCamera(*fGeom);
+        camera->SetName("MHCamera");
+        camera->SetStats(0);
+        camera->SetInvDeepBlueSeaPalette();
+        camera->SetBit(kCanDelete);
+        camera->Draw();
+    }
+
+    camera->SetTitle(str);
+
+    gPad->cd(1);
+
+    if (!usecam)
+    {
+        if (camera->GetEntries()==0)
+            camera->SetBit(MHCamera::kNoLegend);
+    }
+    else
+    {
+        camera->Reset();
+        camera->SetYTitle("arb.cur");
+    }
+
+    TH2 *h=0;
+    if (hashist)
+    {
+        TH2F hist("","", 90, -650, 650, 90, -650, 650);
+        hist.SetMinimum(0);
+        h = (TH2*)hist.DrawCopy("samecont1");
+    }
+
+    const TVector3 zdaz0 = fRaDec.GetZdAz(*fTime, *fObservatory);
+
+    TRotation rot;
+    rot.RotateZ(-zdaz0.Phi());
+    rot.RotateY(-zdaz0.Theta());
+
+    DrawNet(rot);
+
+    MVector3 *radec;
+    TIter Next(&fList);
+
+    while ((radec=(MVector3*)Next()))
+    {
+        const Double_t mag = radec->Magnitude();
+
+        TVector3 star = radec->GetZdAz(*fTime, *fObservatory);
+
+        // Rotate Star into telescope system
+        star *= rot;
+
+        TVector3 mean;
+
+        Int_t num = 0;
+
+        MGeomMirror *mirror = 0;
+        TIter NextM(fMirrors);
+        while ((mirror=(MGeomMirror*)NextM()))
+        {
+            const TVector3 spot = mirror->GetReflection(star, fGeom->GetCameraDist())*1000;
+
+            // calculate mean of all 'stars' hitting the camera plane
+            // by taking the sum of the intersection points between
+            // the light vector and the camera plane
+            mean += spot;
+
+            if (hasdot)
+            {
+                TMarker *m=new TMarker(spot(1), spot(0), 1);
+                m->SetBit(kCannotPick);
+                m->SetBit(kCanDelete);
+                m->SetMarkerColor(kMagenta);
+                m->SetMarkerStyle(kDot);
+                fMapG.Add((Long_t)m, 0);
+            }
+            if (h)
+                h->Fill(spot(1), spot(0), pow(10, -mag/2.5));
+
+            if (usecam)
+                camera->Fill(spot(1), spot(0), pow(10, -mag/2.5));
+
+            num++;
+        }
+
+        // transform meters into millimeters (camera display works with mm)
+        mean *= 1./num;
+
+        DrawStar(mean(1), mean(0), *radec, !hasmean);
+    }
+}
+
+// ------------------------------------------------------------------------
+//
+// Execute a gui event on the camera
+//
+void MAstroCamera::ExecuteEvent(Int_t event, Int_t mp1, Int_t mp2)
+{
+    if (event==kKeyPress && fTime)
+        switch (mp2)
+        {
+        case kKey_Plus:
+            fTime->SetMjd(fTime->GetMjd()+0.25/24);
+            SetBit(kHasChanged);
+            gPad->Modified();
+            gPad->Update();
+            return;
+        case kKey_Minus:
+            fTime->SetMjd(fTime->GetMjd()-0.25/24);
+            SetBit(kHasChanged);
+            gPad->Modified();
+            gPad->Update();
+            return;
+        }
+
+    MAstroCatalog::ExecuteEvent(event, mp1, mp2);
+}
Index: trunk/MagicSoft/Mars/mastro/MAstroCamera.h
===================================================================
--- trunk/MagicSoft/Mars/mastro/MAstroCamera.h	(revision 3457)
+++ trunk/MagicSoft/Mars/mastro/MAstroCamera.h	(revision 3457)
@@ -0,0 +1,39 @@
+#ifndef MARS_MAstroCamera
+#define MARS_MAstroCamera
+
+#ifndef MARS_MAstroCatalog
+#include "MAstroCatalog.h"
+#endif
+
+class TClonesArray;
+
+class MTime;
+class MGeomCam;
+class MGeomMirror;
+class MObservatory;
+
+class MAstroCamera : public MAstroCatalog
+{
+private:
+    MGeomCam     *fGeom;
+    TClonesArray *fMirrors;
+
+    MGeomMirror  *fMirror0;     //!
+
+    Int_t  Convert(const TRotation &rot, TVector2 &v, Int_t type);
+    void   AddPrimitives(Option_t *o);
+    void   SetRangePad() { }
+    void   DrawNet(const TRotation &rot);
+    void   ExecuteEvent(Int_t event, Int_t mp1, Int_t mp2);
+
+public:
+    MAstroCamera();
+    ~MAstroCamera();
+
+    void SetMirrors(TClonesArray *arr);
+    void SetGeom(const MGeomCam &cam);
+
+    ClassDef(MAstroCamera, 1)
+};
+
+#endif
Index: trunk/MagicSoft/Mars/mastro/MAstroCatalog.cc
===================================================================
--- trunk/MagicSoft/Mars/mastro/MAstroCatalog.cc	(revision 3415)
+++ trunk/MagicSoft/Mars/mastro/MAstroCatalog.cc	(revision 3457)
@@ -34,19 +34,22 @@
 
 #include <fstream>
-
+#include <stdlib.h>
+
+#include <KeySymbols.h>
+
+#include <TPad.h> // TPad::GetMaxPickDistance
 #include <TLine.h>
 #include <TMarker.h>
+#include <TCanvas.h>
 #include <TArrayI.h>
+#include <TGToolTip.h>
 #include <TRotation.h>
 #include <TStopwatch.h>
-#include <TVirtualPad.h>
-
-#include <stdlib.h>
 
 #include "MLog.h"
 #include "MLogManip.h"
 
+#include "MTime.h"
 #include "MAstro.h"
-#include "MTime.h"
 #include "MObservatory.h"
 
@@ -66,4 +69,5 @@
     zdaz.SetZdAz(Theta(), alpha-Phi(), Mag());
     zdaz.RotateY(obs.GetPhi()-TMath::Pi()/2);
+
     return zdaz;
 
@@ -83,4 +87,60 @@
 }
 
+MVector3 MVector3::GetRaDec(const MObservatory &obs, Double_t gmst) const
+{
+    if (!fType==kIsZdAz)
+        return MVector3();
+
+    const Double_t alpha = gmst + obs.GetElong();
+
+    MVector3 v(*this);
+    v.RotateY(TMath::Pi()/2-obs.GetPhi());
+
+    MVector3 rd;
+    rd.SetRaDec(alpha-v.Phi(), TMath::Pi()/2-v.Theta(), Mag());
+    return rd;
+
+    /*
+     // ------ The same using slalib, tested in the drive system -------
+     const Double_t alpha = slaGmst(mjd) + obs.GetElong();
+     Double_t el;
+     slaDe2h(fAlpha-ra, dec, obs.GetPhi(), &az, &el);
+     zd = TMath::Pi()/2-el;
+     return;
+     */
+}
+
+MVector3 MVector3::GetRaDec(const MTime &time, MObservatory &obs) const
+{
+    return GetRaDec(obs, time.GetGmst());
+}
+
+MAstroCatalog::MAstroCatalog() : fLimMag(99), fRadiusFOV(99), fToolTip(0), fObservatory(0), fTime(0)
+{
+    fList.SetOwner();
+    fToolTip = new TGToolTip(0, "", 0);
+}
+
+MAstroCatalog::~MAstroCatalog()
+{
+    if (fTime)
+        delete fTime;
+    if (fObservatory)
+        delete fObservatory;
+
+    fToolTip->Hide();
+    delete fToolTip;
+
+    DeleteMap();
+
+    // FIXME: There must be an easier way!
+    TIter Next(gROOT->GetListOfCanvases());
+    TCanvas *c;
+    while ((c=(TCanvas*)Next()))
+        c->Disconnect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", this,
+                      "EventInfo(Int_t,Int_t,Int_t,TObject*)");
+
+}
+
 TString MAstroCatalog::FindToken(TString &line, Char_t tok)
 {
@@ -120,4 +180,6 @@
 Int_t MAstroCatalog::ReadXephem(TString catalog)
 {
+    SetBit(kHasChanged);
+
     gLog << inf << "Reading Xephem catalog: " << catalog << endl;
 
@@ -181,4 +243,5 @@
         MVector3 *star=new MVector3;
         star->SetRaDec(ra0, dec0, mag);
+        star->SetName(name);
         if (star->Angle(fRaDec)*TMath::RadToDeg()>fRadiusFOV)
         {
@@ -197,4 +260,6 @@
 Int_t MAstroCatalog::ReadNGC2000(TString catalog)
 {
+    SetBit(kHasChanged);
+
     gLog << inf << "Reading NGC2000 catalog: " << catalog << endl;
 
@@ -240,4 +305,5 @@
         MVector3 *star=new MVector3;
         star->SetRaDec(ra, dec, mag);
+        star->SetName(row(0, 8));
         if (star->Angle(fRaDec)*TMath::RadToDeg()>fRadiusFOV)
         {
@@ -257,4 +323,6 @@
 Int_t MAstroCatalog::ReadBSC(TString catalog)
 {
+    SetBit(kHasChanged);
+
     gLog << inf << "Reading Bright Star Catalog (BSC5) catalog: " << catalog << endl;
 
@@ -302,4 +370,5 @@
         MVector3 *star=new MVector3;
         star->SetRaDec(ra, dec, mag);
+        star->SetName(row(4,9));
         if (star->Angle(fRaDec)*TMath::RadToDeg()>fRadiusFOV)
         {
@@ -317,16 +386,46 @@
 }
 
-Bool_t MAstroCatalog::Convert(const TRotation &rot, TVector2 &v, Int_t type)
+Int_t MAstroCatalog::Convert(const TRotation &rot, TVector2 &v, Int_t type)
 {
     MVector3 w;
-    w.SetRaDec(v.Y(), v.X()-fRaDec.Phi(), v.Y());
+
+    switch (type)
+    {
+    case 1:
+        w.SetRaDec(v.X()-fRaDec.Phi(), v.Y(), 1);
+        break;
+
+    case 2:
+        if (!fTime || !fObservatory)
+            return kFALSE;
+        w.SetZdAz(v.Y(), v.X(), 1);
+        w = w.GetRaDec(*fTime, *fObservatory);
+        w.RotateZ(-fRaDec.Phi());
+        break;
+
+    default:
+        return kFALSE;
+    }
+
     w *= rot;
 
-    v.Set(w.Phi(), w.Theta());
-
-    return w.Angle(TVector3(1, 0, 0))*TMath::RadToDeg()<=fRadiusFOV;
-}
-
-Bool_t MAstroCatalog::PaintLine(const TVector2 &v, Double_t dx, Double_t dy, const TRotation &rot, Int_t type)
+    // Stretch such, that the X-component is alwas the same. Now
+    // Y and Z contains the crossing point between the star-light
+    // and the plain of a virtual screen (ccd...)
+    if (TestBit(kPlainScreen))
+        w *= TMath::RadToDeg()/w.X();
+    else
+        w.SetMag(TMath::RadToDeg());
+
+    v.Set(w(1), w(2));
+
+    if (w(0)<0)
+        return kERROR;
+
+    return w(1)>gPad->GetX1() && w(2)>gPad->GetY1() &&
+           w(1)<gPad->GetX2() && w(2)<gPad->GetY2();
+}
+
+Bool_t MAstroCatalog::DrawLine(const TVector2 &v, Double_t dx, Double_t dy, const TRotation &rot, Int_t type)
 {
     const TVector2 add(dx*TMath::DegToRad(), dy*TMath::DegToRad());
@@ -335,53 +434,84 @@
     TVector2 v1 = v+add;
 
-    const Bool_t rc0 = Convert(rot, v0, type);
-    const Bool_t rc1 = Convert(rot, v1, type);
-    if (!rc0 && !rc1)
+    const Int_t rc0 = Convert(rot, v0, type);
+    const Int_t rc1 = Convert(rot, v1, type);
+    // Both are kFALSE or both are kERROR
+    if ((rc0|rc1)==kFALSE || (rc0&rc1)==kERROR)
         return kFALSE;
 
-    TLine line;
-    line.SetLineColor(kGreen);
-    line.PaintLine(v0.X(), TMath::Pi()/2-v0.Y(),
-                   v1.X(), TMath::Pi()/2-v1.Y());
+    TLine *line = new TLine(v0.X(), v0.Y(), v1.X(), v1.Y());
+    line->SetBit(kCanDelete);
+    line->SetLineStyle(kDashDotted); //kDashed, kDotted, kDashDotted
+    line->SetLineColor(kWhite+type*2);
+    line->SetBit(kCannotPick);
+    fMapG.Add((Long_t)line, 0);
+
+    const TVector2 deg = v*TMath::RadToDeg();
+    TString txt = type==1 ?
+        Form("Ra=%.1fh  Dec=%.1fd", fmod(deg.X()/15+48, 24),  fmod(deg.Y()+270,180)-90) :
+        Form("Zd=%.1fd  Az=%.1fd",  fmod(deg.Y()+270,180)-90, fmod(deg.X()+720, 360));
+
+    TMarker *tip=new TMarker(v0.X(), v0.Y(), kDot);
+    tip->SetBit(kCanDelete);
+    tip->SetMarkerColor(kWhite+type*2);
+    fMapG.Add((Long_t)tip, (Long_t)new TString(txt));
 
     return kTRUE;
 }
 
-void MAstroCatalog::Paint(const TVector2 &v0, const TRotation &rot, TArrayI &dx, TArrayI &dy, Byte_t type)
-{
+void MAstroCatalog::Draw(const TVector2 &v0, const TRotation &rot, TArrayI &dx, TArrayI &dy, Int_t stepx, Int_t stepy, Int_t type)
+{
+    const TVector2 v1 = v0 + TVector2(dx[0]*TMath::DegToRad(), dy[0]*TMath::DegToRad());
+
+    //    if (TMath::Abs(v1.Y())>TMath::Pi()/2)
+    //        return;
+
+    const Int_t v0x = (int)(v0.X()*TMath::RadToDeg());
+    const Int_t v0y = (int)(v0.Y()*TMath::RadToDeg());
+
     Int_t idx[] = {1, 1, 1, 1};
 
-    Int_t dirs[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
+    Int_t dirs[4][2] = { {0, stepy}, {stepx, 0}, {0, -stepy}, {-stepx, 0} };
 
     for (int i=0; i<dx.GetSize(); i++)
     {
         for (int j=0; j<4; j++)
-            if (dx[i]==dx[0]+dirs[j][0] && dy[i]==dy[0]+dirs[j][1])
+        {
+            const Bool_t rcx0 = (dx[i]+720)%360==(dx[0]+dirs[j][0]+720)%360;
+            const Bool_t rcy0 = (dy[i]+360)%180==(dy[0]+dirs[j][1]+360)%180;
+            if (rcx0&&rcy0)
                 idx[j] = 0;
-    }
-
-    TVector2 v1 = v0 + TVector2(dx[0]*TMath::DegToRad(), dy[0]*TMath::DegToRad());
+        }
+    }
+
+    // Enhance size of array by 1, copy current
+    // position as last entry
+    dx.Set(dx.GetSize()+1);
+    dy.Set(dy.GetSize()+1);
+
+    dx[dx.GetSize()-1] = dx[0];
+    dy[dy.GetSize()-1] = dy[0];
+
+    // Store current positon
+    const Int_t d[2] = { dx[0], dy[0] };
 
     for (int i=0; i<4; i++)
         if (idx[i])
         {
-            dx.Set(dx.GetSize()+1);
-            dy.Set(dy.GetSize()+1);
-
-            dx[dx.GetSize()-1] = dx[0];
-            dy[dy.GetSize()-1] = dy[0];
-
-            dx[0] += dirs[i][0];
-            dy[0] += dirs[i][1];
-
-            if (PaintLine(v1, dirs[i][0], dirs[i][1], rot, type))
-                Paint(v0, rot, dx, dy, type);
-
-            dx[0] -= dirs[i][0];
-            dy[0] -= dirs[i][1];
+            // Calculate new position
+            //dx[0] = (d[0]+dirs[i][0]+540-v0x)%360-180+v0x;
+            //dy[0] = (d[1]+dirs[i][1]+270-v0y)%180- 90+v0y;
+            dx[0] = d[0]+dirs[i][0];
+            dy[0] = d[1]+dirs[i][1];
+
+            // Draw corresponding line and iterate through grid
+            if (DrawLine(v1, dirs[i][0], dirs[i][1], rot, type))
+                Draw(v0, rot, dx, dy, stepx, stepy, type);
+
+            dx[0]=d[0]; dy[0]=d[1];
         }
 }
 
-void MAstroCatalog::PaintNet(const TVector2 &v0, const TRotation &rot, Int_t type)
+void MAstroCatalog::DrawNet(const TVector2 &v0, const TRotation &rot, Int_t type)
 {
     //const Double_t step = TMath::DegToRad();
@@ -390,46 +520,96 @@
     TArrayI dy(1);
 
+    // align to 1deg boundary
     TVector2 v = v0*TMath::RadToDeg();
-    v.Set(TMath::Floor(v.X()), TMath::Floor(v.Y()));
+    v.Set((Float_t)TMath::Nint(v.X()), (Float_t)TMath::Nint(v.Y()));
+
+    // calculate stepsizes based on visible FOV
+    Int_t stepx=1;
+    if (fabs(v.Y())>90-fRadiusFOV || fabs(v.Y())<fRadiusFOV)
+        stepx = 180/10;
+    else
+    {
+        // This is a rough estimate how many degrees are visible
+        const Float_t m = log(fRadiusFOV/180.)/log(90./fRadiusFOV-1);
+        const Float_t t = log(180.)-m*log(fRadiusFOV);
+        const Int_t n = (Int_t)(exp(m*log(90-fabs(v.Y()))+t)+0.5);
+        stepx = n<4 ? 1 : n/4;
+    }
+
+    const Int_t n = (Int_t)(fRadiusFOV+1);
+    Int_t stepy = n<4 ? 1 : n/4;
+
+    // align stepsizes to be devisor or 180 and 90
+    while (180%stepx)
+        stepx++;
+    while (90%stepy)
+        stepy++;
+
+    // align to step-size boundary
+    while ((int)(v.X())%stepx)
+        v.Set(v.X()+1, v.Y());
+
+    while ((int)(v.Y())%stepy)
+        v.Set(v.X(), v.Y()+1);
+
+    // draw...
     v *= TMath::DegToRad();
-
-    Paint(v, rot, dx, dy, type);
+    Draw(v, rot, dx, dy, stepx, stepy, type);
 }
 
 void MAstroCatalog::Paint(Option_t *o)
 {
-    Double_t ra = fRaDec.Phi();
-    Double_t dec = TMath::Pi()/2-fRaDec.Theta();
-
-    TIter Next(&fList);
-    TVector3 *v;
-
-    Double_t minra=360, maxra=0, mindec=360, maxdec=0;
-
-    while ((v=(TVector3*)Next()))
-    {
-        minra = TMath::Min(minra, v->Phi());
-        maxra = TMath::Max(maxra, v->Phi());
-
-        mindec = TMath::Min(mindec, TMath::Pi()/2-v->Theta());
-        maxdec = TMath::Max(maxdec, TMath::Pi()/2-v->Theta());
-    }
-
-    cout << gPad << endl;
-
-    cout << "Minra: " << (minra-ra)*TMath::RadToDeg() << endl;
-    cout << "Maxra: " << (maxra-ra)*TMath::RadToDeg() << endl;
-
-    cout << "Mindec: " << (mindec-dec)*TMath::RadToDeg() << endl;
-    cout << "Maxdec: " << (maxdec-dec)*TMath::RadToDeg() << endl;
-
-    //gPad->Range(minra-ra, mindec-dec, maxra-ra, maxdec-dec);
-    gPad->Range(-fRadiusFOV*TMath::DegToRad()/TMath::Sqrt(2.), -fRadiusFOV*TMath::DegToRad()/TMath::Sqrt(2.),
-                fRadiusFOV*TMath::DegToRad()/TMath::Sqrt(2.),  fRadiusFOV*TMath::DegToRad()/TMath::Sqrt(2.));
-
-    Next.Reset();
-
-    cout << "Dec: " << dec*TMath::RadToDeg() << endl;
-    cout << "Ra:  " << ra*TMath::RadToDeg() << endl;
+    if (!gPad->IsBatch())
+        gVirtualX->ClearWindow();
+
+    if (TestBit(kHasChanged))
+        DrawPrimitives(o);
+}
+
+void MAstroCatalog::DrawStar(Double_t x, Double_t y, const TVector3 &v, Bool_t transparent)
+{
+    const Double_t ra  = v.Phi()*TMath::RadToDeg()/15;
+    const Double_t dec = (TMath::Pi()/2-v.Theta())*TMath::RadToDeg();
+
+    TString str = v.GetName();
+    str += Form(":  Ra=%.1fh", ra);
+    str += Form("  Dec=%.1fd", dec);
+    str += Form("  Mag=%.1f", -2.5*log10(v.Mag()));
+
+    // draw star on the camera display
+    TMarker *tip=new TMarker(x, y, transparent ? kDot : kFullDotLarge);;
+    tip->SetMarkerColor(kBlack);
+    tip->SetBit(kCanDelete);
+    tip->SetBit(kCannotPick);
+    fMapG.Add((Long_t)tip, (Long_t)new TString(str));
+}
+
+void MAstroCatalog::Update()
+{
+    if (gPad && TestBit(kMustCleanup))
+    {
+        SetBit(kHasChanged);
+        gPad->Modified();
+    }
+}
+
+void MAstroCatalog::SetTime(const MTime &time)
+{
+    if (fTime)
+        delete fTime;
+    fTime=(MTime*)time.Clone();
+}
+
+void MAstroCatalog::SetObservatory(const MObservatory &obs)
+{
+    if (fObservatory)
+        delete fObservatory;
+    fObservatory=(MObservatory*)obs.Clone();
+}
+
+void MAstroCatalog::AddPrimitives(Option_t *o)
+{
+    const Double_t ra  = fRaDec.Phi();
+    const Double_t dec = TMath::Pi()/2-fRaDec.Theta();
 
     // Precalc Sin/Cos...
@@ -437,31 +617,215 @@
     trans.Rotate(dec, TVector3(0, 1, 0));
 
+    const TVector3 zdaz0 = fRaDec.GetZdAz(*fTime, *fObservatory);
+    TVector2 zdaz(zdaz0.Phi(), zdaz0.Theta());
+    MAstroCatalog::DrawNet(zdaz, trans, 2);
+
+    TVector2 radec(ra, dec);
+    MAstroCatalog::DrawNet(radec, trans, 1);
+
+    TIter Next(&fList);
+    TVector3 *v=0;
+    while ((v=(TVector3*)Next()))
+    {
+        // FIXME: Check Magnitude!
+        TVector2 s(v->Phi(), TMath::Pi()/2-v->Theta());
+        if (Convert(trans, s, 1)==kTRUE)
+            DrawStar(s.X(), s.Y(), *v, kFALSE);
+    }
+}
+
+void MAstroCatalog::SetRangePad()
+{
+     const Double_t edge = fRadiusFOV/TMath::Sqrt(2.);
+     gPad->Range(-edge, -edge, edge, edge);
+
+     cout << gPad->GetWw() << " " << gPad->GetWh() << endl;
+
+     const Float_t w = gPad->GetWw();
+     const Float_t h = gPad->GetWh();
+
+     if (w<h)
+         gPad->Range(-edge, -edge*h/w, edge, edge*h/w);
+     else
+         gPad->Range(-edge*w/h, -edge, edge*w/h, edge);
+}
+
+void MAstroCatalog::DrawPrimitives(Option_t *o)
+{
+    DeleteMap();
+
+    SetRangePad();
+
     TStopwatch clk;
     clk.Start();
-
-    TMarker mark;
-    mark.SetMarkerColor(kBlack);
-    mark.SetMarkerStyle(kCircle);
-    while ((v=(TVector3*)Next()))
-    {
-        MVector3 v0;
-        v0.SetRaDec(v->Phi()-ra, TMath::Pi()/2-v->Theta(), 1);
-        v0 *= trans;
-
-        mark.SetMarkerSize((fLimMag-TMath::Log(v->Mag()))/4);
-        mark.PaintMarker(v0.Phi(), TMath::Pi()/2-v0.Theta());
-    }
-
-    TMarker m;
-    m.SetMarkerStyle(kCross);
-    m.PaintMarker(0, 0);
-
-    m.SetMarkerColor(kRed);
-    m.SetMarkerStyle(kFullDotSmall);
-
-    TVector2 v0(ra, dec);
-    PaintNet(v0, trans);
-
+    AddPrimitives(o);
     clk.Stop();
     clk.Print();
-}
+
+    // Append all objects to pad
+    DrawMap();
+
+    ResetBit(kHasChanged);
+}
+
+void MAstroCatalog::Draw(Option_t *o)
+{
+    TObject::Draw(o);
+
+    if (!TestBit(kHasChanged))
+        DrawPrimitives(o);
+
+    // Connect all TCanvas::ProcessedEvent to this->EventInfo
+    // This means, that after TCanvas has processed an event
+    // EventInfo of this class is called, see TCanvas::HandleInput
+    gPad->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
+                               "MAstroCatalog", this,
+                               "EventInfo(Int_t,Int_t,Int_t,TObject*)");
+
+    // Do this instead of fListG.Draw, because
+    // TCollection overwrites Draw
+    // Would be nice, but doesn't work because the single
+    // graphical object are not handled by TPad anymore...
+    //    fListG.AppendPad();
+}
+
+// --------------------------------------------------------------------------
+//
+// This function was connected to all created canvases. It is used
+// to redirect GetObjectInfo into our own status bar.
+//
+// The 'connection' is done in AddTab
+//
+void MAstroCatalog::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
+{
+    if (!selected)
+        return;
+
+    TCanvas *c = (TCanvas*)gTQSender;
+
+    TVirtualPad* save=gPad;
+
+    gPad = c ? c->GetSelectedPad() : NULL;
+    if (!gPad)
+        return;
+
+    switch (event)
+    {
+    case kMouseMotion:
+        {
+            TString *s = (TString*)fMapG.GetValue((Long_t)selected);
+            if (!fToolTip->IsMapped() && s)
+                ShowToolTip(px, py, *s);
+        }
+        break;
+
+    case kMouseLeave:
+        if (fToolTip->IsMapped())
+            fToolTip->Hide();
+        break;
+
+    case kKeyPress: // Unresolved keyboard event
+        /*
+        switch (px)
+        {
+        case kKey_Plus:
+        case kKey_Minus:*/
+            ExecuteEvent(kKeyPress, px, py);/*
+            break;
+        }
+        break;*/
+    }
+
+    gPad=save;
+}
+
+void MAstroCatalog::ExecuteEventKbd(Int_t keycode, Int_t keysym)
+{
+    Double_t dra =0;
+    Double_t ddec=0;
+
+    switch (keysym)
+    {
+    case kKey_Left:
+        dra = -TMath::DegToRad();
+        break;
+    case kKey_Right:
+        dra = +TMath::DegToRad();
+        break;
+    case kKey_Up:
+        ddec = +TMath::DegToRad();
+        break;
+    case kKey_Down:
+        ddec = -TMath::DegToRad();
+        break;
+    case kKey_Plus:
+        SetRadiusFOV(fRadiusFOV+1);
+        break;
+    case kKey_Minus:
+        SetRadiusFOV(fRadiusFOV-1);
+        break;
+
+    default:
+        return;
+    }
+
+    const Double_t r = fRaDec.Phi();
+    const Double_t d = TMath::Pi()/2-fRaDec.Theta();
+
+    SetRaDec(r+dra, d+ddec);
+
+    gPad->Update();
+}
+
+// ------------------------------------------------------------------------
+//
+// Execute a gui event on the camera
+//
+void MAstroCatalog::ExecuteEvent(Int_t event, Int_t mp1, Int_t mp2)
+{
+    if (!TestBit(kGuiActive))
+        return;
+
+    if (event==kKeyPress)
+        ExecuteEventKbd(mp1, mp2);
+
+}
+
+Int_t MAstroCatalog::DistancetoPrimitive(Int_t px, Int_t py)
+{
+    Int_t min = INT_MAX;
+
+    Long_t key, val;
+    TExMapIter map(&fMapG);
+    while (map.Next(key, val))
+    {
+        TObject *o=(TObject*)key;
+
+        const Int_t d = o->DistancetoPrimitive(px, py);
+
+        if (d<TPad::GetMaxPickDistance())
+            return 0;
+
+        if (d<min)
+            min=d;
+    }
+
+    return min;
+}
+
+void MAstroCatalog::ShowToolTip(Int_t px, Int_t py, const char *txt)
+{
+    Int_t x=0;
+    Int_t y=0;
+
+    const Window_t id1 = gVirtualX->GetWindowID(gPad->GetCanvasID());
+    const Window_t id2 = fToolTip->GetParent()->GetId();
+
+    Window_t id3;
+    gVirtualX->TranslateCoordinates(id1, id2, px, py, x, y, id3);
+
+    // Show tool tip
+    fToolTip->SetText(txt);
+    fToolTip->Show(x+4, y+4);
+}
+
Index: trunk/MagicSoft/Mars/mastro/MAstroCatalog.h
===================================================================
--- trunk/MagicSoft/Mars/mastro/MAstroCatalog.h	(revision 3415)
+++ trunk/MagicSoft/Mars/mastro/MAstroCatalog.h	(revision 3457)
@@ -4,4 +4,7 @@
 #ifndef ROOT_TVector3
 #include <TVector3.h>
+#endif
+#ifndef ROOT_TExMap
+#include <TExMap.h>
 #endif
 #ifndef ROOT_TList
@@ -12,7 +15,9 @@
 class MObservatory;
 class TArrayI;
+class TGToolTip;
 
 class MVector3 : public TVector3
 {
+private:
     enum VectorType_t
     {
@@ -26,4 +31,6 @@
     VectorType_t fType;
 
+    TString fName;
+
 public:
     /*
@@ -34,26 +41,31 @@
     MVector3() { fType=kIsInvalid; }
     MVector3(const TVector3 &v3) : TVector3(v3) { fType=kIsArbitrary; }
-    Double_t Magnitude() const { return TMath::Log(Mag()); }
+    Double_t Magnitude() const { return -2.5*TMath::Log10(Mag()); }
 
     void SetRaDec(Double_t ra, Double_t dec, Double_t mag)
     {
         fType = kIsRaDec;
-        SetMagThetaPhi(exp(mag), TMath::Pi()/2-dec, ra);
+        SetMagThetaPhi(pow(10, -mag/2.5), TMath::Pi()/2-dec, ra);
     }
+    void SetName(const TString &str) { fName = str.Strip(TString::kBoth); }
     void SetZdAz(Double_t zd, Double_t az, Double_t mag)
     {
         fType = kIsZdAz;
-        SetMagThetaPhi(exp(mag), zd, az);
+        SetMagThetaPhi(pow(10, -mag/2.5), zd, az);
     }
     void SetAltAz(Double_t alt, Double_t az, Double_t mag)
     {
         fType = kIsAltAz;
-        SetMagThetaPhi(exp(mag), TMath::Pi()/2-alt, az);
+        SetMagThetaPhi(pow(10, -mag/2.5), TMath::Pi()/2-alt, az);
     }
+
+    const char *GetName() const { return fName; }
 
     MVector3 GetZdAz(const MObservatory &obs, Double_t gmst) const;
     MVector3 GetZdAz(const MTime &time, MObservatory &obs) const;
+    MVector3 GetRaDec(const MObservatory &obs, Double_t gmst) const;
+    MVector3 GetRaDec(const MTime &time, MObservatory &obs) const;
 
-    ClassDef(MVector3, 0)
+    ClassDef(MVector3, 1)
 };
 
@@ -63,7 +75,8 @@
     Double_t fLimMag;    // [1]   Limiting Magnitude
     Double_t fRadiusFOV; // [deg] Radius of Field of View
-    MVector3 fRaDec;     // pointing position
 
-    TList fList;
+    TGToolTip *fToolTip; //!
+
+    void ShowToolTip(Int_t px, Int_t py, const char *txt);
 
     TString FindToken(TString &line, Char_t tok=',');
@@ -74,15 +87,97 @@
     Float_t atof(const TString &s);
 
-public:
-    MAstroCatalog() : fLimMag(99), fRadiusFOV(99)
+    Bool_t fPlainScreen;  //! Just a dummy!!!! ([Set,Is]Freezed)
+
+protected:
+    enum {
+        kHasChanged  = BIT(15),
+        kGuiActive   = BIT(16),
+        kPlainScreen = BIT(17)
+    };
+
+    TExMap   fMapG;
+    TList    fList;      // List of stars loaded
+    MVector3 fRaDec;     // pointing position
+
+    MObservatory *fObservatory; // Possible obervatora location
+    MTime        *fTime;        // Possible observation time
+
+    virtual Int_t  Convert(const TRotation &rot, TVector2 &v, Int_t type=0);
+    virtual Bool_t DrawLine(const TVector2 &v0, Double_t dx, Double_t dy, const TRotation &rot, Int_t type);
+    virtual void   AddPrimitives(Option_t *o);
+    virtual void   DrawPrimitives(Option_t *o);
+    virtual void   SetRangePad();
+    void  Draw(const TVector2 &v0, const TRotation &rot, TArrayI &dx, TArrayI &dy, Int_t stepx, Int_t stepy, Int_t type);
+    void  DrawNet(const TVector2 &v0, const TRotation &rot, Int_t type);
+    void  DrawStar(Double_t x, Double_t y, const TVector3 &v, Bool_t t);
+    void  Paint(Option_t *o="");
+    Int_t DistancetoPrimitive(Int_t px, Int_t py);
+    void  Update();
+
+    void ExecuteEventKbd(Int_t keycode, Int_t keysym);
+    void ExecuteEvent(Int_t event, Int_t mp1, Int_t mp2);
+
+    void DeleteMap()
     {
-        fList.SetOwner();
+        Long_t key, val;
+        TExMapIter map(&fMapG);
+        while (map.Next(key, val))
+        {
+            delete (TObject*)(key);
+            if (!val)
+                continue;
+
+            delete (TString*)(val);
+         /*
+            Long_t key2, val2;
+            TExMapIter map2(&fMapG);
+            while (map2.Next(key2, val2))
+                if (val==val2)
+                {
+                    delete (TObject*)key;
+                    fMapG.Remove(key);
+                }*/
+        }
+        fMapG.Delete();
+    }
+    void DrawMap()
+    {
+        Long_t key, val;
+        TExMapIter map(&fMapG);
+        while (map.Next(key, val))
+            ((TObject*)key)->Draw();
     }
 
-    void SetLimMag(Double_t mag)             { fLimMag=mag; }
-    void SetRadiusFOV(Double_t deg)          { fRadiusFOV=deg; }
-    void SetRaDec(Double_t ra, Double_t dec) { fRaDec.SetRaDec(ra, dec, 1); }
-    void SetRaDec(const TVector3 &v)         { fRaDec=v; }
-    void Delete(Option_t *o="")              { fList.Delete(o); }
+public:
+    MAstroCatalog();
+    ~MAstroCatalog();
+
+    void SetTime(const MTime &time);
+    void SetObservatory(const MObservatory &obs);
+    void SetLimMag(Double_t mag) { fLimMag=mag;    Update(); } // *MENU* *ARGS={mag=>fLimMag}
+    void SetRadiusFOV(Double_t deg)
+    {
+        //const Double_t max = TestBit(kPlainScreen) ? 90 : 55;
+        const Double_t max = TestBit(kPlainScreen) ? 180 : 90;
+        if (deg>max)
+            deg=max;
+        if (deg<=0)
+            deg=1;
+
+        fRadiusFOV=deg;
+
+        Update();
+    } // *MENU* *ARGS={deg=>fRadiusFOV}
+    void SetRaDec(Double_t ra, Double_t dec) { fRaDec.SetRaDec(ra, dec, 1); Update(); }
+    void SetRaDec(const TVector3 &v)         { fRaDec=v; Update(); }
+    void SetGuiActive(Bool_t b=kTRUE)        { b ? SetBit(kGuiActive) : ResetBit(kGuiActive); }
+
+    void   SetPlainScreen(Bool_t b=kTRUE)    { b ? SetBit(kPlainScreen) : ResetBit(kPlainScreen); Update(); } // *TOGGLE*
+    Bool_t IsPlainScreen() const             { return TestBit(kPlainScreen); }
+
+    Double_t GetLimMag() const { return fLimMag; }
+    Double_t GetRadiusFOV() const { return fRadiusFOV; }
+
+    void Delete(Option_t *o="") { fList.Delete(); DeleteMap(); }
 
     Int_t ReadXephem(TString catalog = "/usr/X11R6/lib/xephem/catalogs/YBS.edb");
@@ -94,12 +189,9 @@
     TList *GetList() { return &fList; }
 
-    virtual Bool_t Convert(const TRotation &rot, TVector2 &v, Int_t type);
-    virtual Bool_t PaintLine(const TVector2 &v0, Double_t dx, Double_t dy, const TRotation &rot, Int_t type);
+    void Draw(Option_t *o="");
 
-    void Paint(const TVector2 &v0, const TRotation &rot, TArrayI &dx, TArrayI &dy, Byte_t type);
-    void PaintNet(const TVector2 &v0, const TRotation &rot, Int_t type=0);
-    void Paint(Option_t *o="");
+    void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected);
 
-    ClassDef(MAstroCatalog, 0)
+    ClassDef(MAstroCatalog, 1)
 };
 #endif
