source: trunk/MagicSoft/Mars/mbase/MGMap.cc@ 4602

Last change on this file since 4602 was 4108, checked in by moralejo, 21 years ago
*** empty log message ***
File size: 15.7 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 05/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2002-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MGMap
28// =====
29//
30// This Map of TObjects connects TObjects with a TString. It can be used
31// to create maps which displays tooltips it the mouse is above the objects.
32//
33// It is also a tool to convert TObjects which are drawn into
34// a bitmap or to draw them into a TGFrame. Because in both cases the
35// support for drawing such object must be programmed explicitly only
36// simple objects (TLine, TMarker, etc) are supported.
37//
38//////////////////////////////////////////////////////////////////////////////
39#include "MGMap.h"
40
41#include <limits.h> // INT_MAX
42
43#include <TPad.h> // gPad, TPad::GetMaxDistance()
44
45#include <TLine.h>
46#include <TMarker.h>
47
48#include <TGToolTip.h>
49
50ClassImp(MGMap);
51
52using namespace std;
53
54//
55// THIS IS A WORKAROUND TO GET A MORE DIRECT ACCESS TO TGX11
56//
57/*
58#include <TGX11.h>
59class MGX11 : public TGX11
60{
61public:
62 ULong_t GetGc(Int_t which) const
63 {
64 return (ULong_t)*TGX11::GetGC(which);
65 }
66 void DrawLine(Drawable_t id, TObject *o, Int_t dx, Int_t dy, Float_t r)
67 {
68 TLine *l = dynamic_cast<TLine*>(o);
69 if (!l)
70 return;
71
72 SetLineColor(l->GetLineColor());
73 SetLineWidth(l->GetLineWidth());
74 SetLineStyle(l->GetLineStyle());
75
76 if (l->GetLineColor()==kRed)
77 SetLineColor(50);
78 if (l->GetLineColor()==kBlue)
79 SetLineColor(9);
80
81 gVirtualX->DrawLine(id, GetGc(0),
82 dx+(l->GetX1()/r), dy-(l->GetY1()/r),
83 dx+(l->GetX2()/r), dy-(l->GetY2()/r));
84 }
85 void DrawMarker(Drawable_t id, TObject *o, Int_t dx, Int_t dy, Float_t r)
86 {
87 TMarker *m = dynamic_cast<TMarker*>(o);
88 if (!m)
89 return;
90
91 SetLineColor(m->GetMarkerColor());
92 SetLineStyle(kSolid);
93 SetLineWidth(1);
94
95 const Double_t x = dx+(m->GetX()/r);
96 const Double_t y = dy-(m->GetY()/r);
97 const Int_t l = (Int_t)(m->GetMarkerSize()*5)+1;
98
99 switch (m->GetMarkerStyle())
100 {
101 case kPlus:
102 gVirtualX->DrawLine(id, GetGc(0), x-l, y, x+l, y);
103 gVirtualX->DrawLine(id, GetGc(0), x, y-l, x, y+l);
104 break;
105 case kCircle:
106 for (int i=0; i<8; i++)
107 gVirtualX->DrawLine(id, GetGc(0),
108 x+l*cos(i*TMath::TwoPi()/8),
109 y+l*sin(i*TMath::TwoPi()/8),
110 x+l*cos(((i+1)%8)*TMath::TwoPi()/8),
111 y+l*sin(((i+1)%8)*TMath::TwoPi()/8));
112 break;
113 case kCross:
114 gVirtualX->DrawLine(id, GetGc(0), x-l, y-l, x+l, y+l);
115 gVirtualX->DrawLine(id, GetGc(0), x-l, y+l, x+l, y-l);
116 break;
117 }
118 }
119};
120*/
121// --------------------------------------------------------------------------
122//
123// Constructor. For more details see TExMap
124//
125MGMap::MGMap(Int_t mapSize) : TExMap(mapSize)//, fToolTip(0)
126{
127// fToolTip = new TGToolTip(0, "", 0);
128}
129
130// --------------------------------------------------------------------------
131//
132// Destructor. Deletes all objects of the map if kIsOwner is set via
133// SetOwner.
134//
135MGMap::~MGMap()
136{
137// fToolTip->Hide();
138// delete fToolTip;
139
140 if (TestBit(kIsOwner))
141 Delete();
142}
143
144// --------------------------------------------------------------------------
145//
146// Add an TObject to be drawn and if necessary a corresponding TString
147// to the Map. You must take care of deleting both objects if SetOwner()
148// was not called. Otherwise MGMap takes the ownership of the objects.
149//
150void MGMap::Add(TObject *k, TString *v)
151{
152 TExMap::Add((ULong_t)GetSize(), (Long_t)k, (Long_t)v);
153}
154
155// --------------------------------------------------------------------------
156//
157// Delete all objects stored in the TExMap
158//
159void MGMap::Delete(Option_t *opt)
160{
161 Long_t key, val;
162 TExMapIter map(this);
163 while (map.Next(key, val))
164 {
165 delete (TObject*)(key);
166 if (!val)
167 continue;
168
169 delete (TString*)(val);
170 /*
171 Long_t key2, val2;
172 TExMapIter map2(&fMapG);
173 while (map2.Next(key2, val2))
174 if (val==val2)
175 {
176 delete (TObject*)key;
177 fMapG.Remove(key);
178 }
179 */
180 }
181 TExMap::Delete();
182}
183
184// --------------------------------------------------------------------------
185//
186// Paint all TObjects (which are supported) to a drawable with Id id.
187// Scale is the distance of the center of your drawable to one edge in
188// user coordinates.
189//
190// FIXME: Currently the width and height is hardcoded to 768x576 -
191// find a way to get it from the drawable.
192//
193/*
194void MGMap::Paint(Drawable_t id, Float_t scale)
195{
196 if (id==0 && gPad)
197 id = gVirtualX->GetWindowID(gPad->GetPixmapID());
198
199 const Int_t w = 768;
200 const Int_t h = 576;
201
202 scale /= TMath::Hypot((float)w, (float)h)/2;
203
204 Long_t key, val;
205 TExMapIter map(this);
206 while (map.Next(key, val))
207 {
208 TObject *o = (TObject*)key;
209 ((MGX11*)gVirtualX)->DrawLine(id, o, w/2, h/2, scale);
210 ((MGX11*)gVirtualX)->DrawMarker(id, o, w/2, h/2, scale);
211 }
212}
213*/
214
215// --------------------------------------------------------------------------
216//
217// Convert root colors to arbitrary bitmap coordinates
218//
219UChar_t MGMap::Color(int col)
220{
221 switch (col)
222 {
223 case kBlack: return 0;
224 case kWhite: return 0xff;
225 case kYellow: return 0x0f;
226 case kRed: return 2;
227 case kGreen: return 2<<2;
228 case kBlue: return 2<<4;
229 default:
230 return 0;
231 }
232}
233
234// --------------------------------------------------------------------------
235//
236// Draw a line into the buffer (size w*h) from (x1, y1) to (x2, y2) with
237// the color col and the line style style (default: solid)
238//
239void MGMap::DrawLine(UChar_t *buf, int w, int h, Float_t x1, Float_t y1, Float_t x2, Float_t y2, UChar_t col, Int_t style)
240{
241 const Int_t step = style==kSolid?1:3;
242 const Double_t len = TMath::Hypot(x2-x1, y2-y1);
243 const Double_t dx = (x2-x1)/len*step;
244 const Double_t dy = (y2-y1)/len*step;
245
246 Double_t x = x1;
247 Double_t y = y1;
248
249 for (int i=0; i<len; i+=step)
250 {
251 x+= dx;
252 y+= dy;
253
254 const Int_t iy = TMath::Nint(y);
255 if (iy<0 || iy>=h)
256 continue;
257
258 const Int_t ix = TMath::Nint(x);
259 if (ix<0 || ix>=w)
260 continue;
261
262 buf[ix+iy*w] = col;
263 }
264}
265
266// --------------------------------------------------------------------------
267//
268// Draw a box into the buffer (size w*h) from (x1, y1) to (x2, y2) with
269// the color col and the line style style (default: solid)
270//
271void MGMap::DrawBox(UChar_t *buf, int w, int h, Float_t x1, Float_t y1, Float_t x2, Float_t y2, UChar_t col, Int_t style)
272{
273 DrawLine(buf, w, h, x1, y1, x2, y1, col, style);
274 DrawLine(buf, w, h, x1, y2, x2, y1, col, style);
275 DrawLine(buf, w, h, x1, y1, x1, y2, col, style);
276 DrawLine(buf, w, h, x2, y1, x2, y2, col, style);
277}
278
279// --------------------------------------------------------------------------
280//
281// Draw a circle into the buffer (size w*h) around (x, y) with radius r and
282// the color col.
283//
284void MGMap::DrawCircle(UChar_t *buf, int w, int h, Float_t x, Float_t y, Float_t r, UChar_t col)
285{
286 const Int_t n = TMath::Nint(sqrt(2.)*r*TMath::Pi()/2);
287 for (int i=0; i<n-1; i++)
288 {
289 const Double_t angle = TMath::TwoPi()*i/n;
290
291 const Double_t dx = r*cos(angle);
292 const Double_t dy = r*sin(angle);
293
294 const Int_t x1 = TMath::Nint(x+dx);
295 const Int_t x2 = TMath::Nint(x-dx);
296
297 const Int_t y1 = TMath::Nint(y+dy);
298 if (y1>=0 && y1<h)
299 {
300 if (x1>=0 && x1<w)
301 buf[x1+y1*w] = col;
302
303 if (x2>=0 && x2<w)
304 buf[x2+y1*w] = col;
305 }
306
307 const Int_t y2 = TMath::Nint(y-dy);
308 if (y2>=0 && y2<h)
309 {
310 if (x1>=0 && x1<w)
311 buf[x1+y2*w] = col;
312
313 if (x2>=0 && x2<w)
314 buf[x2+y2*w] = col;
315 }
316 }
317}
318
319// --------------------------------------------------------------------------
320//
321// Draw a dot into the buffer (size w*h) at (x, y) with color col.
322//
323void MGMap::DrawDot(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, UChar_t col)
324{
325 const Int_t x1 = TMath::Nint(cx);
326 const Int_t y1 = TMath::Nint(cy);
327
328 if (x1>=0 && y1>=0 && x1<w && y1<h)
329 buf[x1+y1*w] = col;
330}
331
332// --------------------------------------------------------------------------
333//
334// Draw a line into the buffer. The TObject must be a TLine.
335// Currently only solid and non sloid line are supported.
336//
337void MGMap::DrawLine(TObject *o, UChar_t *buf, int w, int h, Double_t scale)
338{
339 TLine *l = dynamic_cast<TLine*>(o);
340 if (!l)
341 return;
342
343 const Double_t x1 = 0.5*w-(l->GetX1()/scale);
344 const Double_t x2 = 0.5*w-(l->GetX2()/scale);
345 const Double_t y1 = 0.5*h-(l->GetY1()/scale);
346 const Double_t y2 = 0.5*h-(l->GetY2()/scale);
347
348 const Int_t col = Color(l->GetLineColor());
349 DrawLine(buf, w, h, x1, y1, x2, y2, col, l->GetLineStyle());
350}
351
352void MGMap::DrawMultiply(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, Float_t size, UChar_t col)
353{
354 DrawLine(buf, w, h, cx-size, cy-size, cx+size, cy+size, col);
355 DrawLine(buf, w, h, cx+size, cy-size, cx-size, cy+size, col);
356}
357
358void MGMap::DrawCross(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, Float_t size, UChar_t col)
359{
360 DrawLine(buf, w, h, cx-size, cy, cx+size, cy, col);
361 DrawLine(buf, w, h, cx, cy-size, cx, cy+size, col);
362}
363
364// --------------------------------------------------------------------------
365//
366// Draw marker into the buffer. The TObject must be a TMarker.
367// Currently kCircle, kMultiply and KDot are supported.
368//
369void MGMap::DrawMarker(TObject *o, UChar_t *buf, int w, int h, Double_t scale)
370{
371 TMarker *m = dynamic_cast<TMarker*>(o);
372 if (!m)
373 return;
374
375 Double_t x = 0.5*w-(m->GetX()/scale);
376 Double_t y = 0.5*h-(m->GetY()/scale);
377
378 Int_t col = Color(m->GetMarkerColor());
379
380 switch (m->GetMarkerStyle())
381 {
382 case kCircle:
383 DrawCircle(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
384 break;
385 case kDot:
386 DrawDot(buf, w, h, x, y, col);
387 break;
388 case kMultiply:
389 DrawMultiply(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
390 break;
391 case kCross:
392 DrawCross(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
393 break;
394 }
395}
396
397// --------------------------------------------------------------------------
398//
399// Paint all elements to the pad by calling their Paint() function
400//
401void MGMap::Paint(Option_t *o)
402{
403 Long_t key, val;
404 TExMapIter map(this);
405 while (map.Next(key, val))
406 ((TObject*)key)->Paint();
407}
408
409// --------------------------------------------------------------------------
410//
411// Paint all objects into a buffer of w*h UChar_ts. The scale
412// gives you the conversio factor to convert pad coordinates into
413// buffer pixels - it is the distance from the center of the buffer
414// to one of its edges.
415//
416void MGMap::Paint(UChar_t *buf, int w, int h, Float_t scale)
417{
418 scale /= TMath::Hypot((float)w, (float)h)/2;
419
420 Long_t key, val;
421 TExMapIter map(this);
422 while (map.Next(key, val))
423 {
424 TObject *o = (TObject*)key;
425 DrawLine(o, buf, w, h, scale);
426 DrawMarker(o, buf, w, h, scale);
427 }
428}
429
430// --------------------------------------------------------------------------
431//
432// Search for an object at px, py. Return the pointer to it
433// if found. Set str accordingly if a corresponding TString is found.
434//
435TObject *MGMap::PickObject(Int_t px, Int_t py, TString &str) const
436{
437 Long_t key, val;
438 TExMapIter map(this);
439 while (map.Next(key, val))
440 {
441 if (!val)
442 continue;
443
444 TObject *o=(TObject*)key;
445 if (o->DistancetoPrimitive(px, py)>TPad::GetMaxPickDistance())
446 continue;
447
448 str = *(TString*)val;
449 return o;
450 }
451 return NULL;
452}
453
454// ------------------------------------------------------------------------
455//
456// Returns string containing info about the object at position (px,py).
457// Returned string will be re-used (lock in MT environment).
458// The text will be truncated to 128 charcters
459//
460char *MGMap::GetObjectInfo(Int_t px, Int_t py) const
461{
462 TString str;
463 PickObject(px, py, str);
464
465 static char txt[129];
466 txt[128]=0;
467
468 return strncpy(txt, str.Data(), 128);
469}
470
471// --------------------------------------------------------------------------
472//
473// Calculate distance to primitive by checking all gui elements
474//
475Int_t MGMap::DistancetoPrimitive(Int_t px, Int_t py)
476{
477 Int_t min = INT_MAX;
478
479 Long_t key, val;
480 TExMapIter map(this);
481 while (map.Next(key, val))
482 {
483 TObject *o=(TObject*)key;
484
485 const Int_t d = o->DistancetoPrimitive(px, py);
486
487 if (d<TPad::GetMaxPickDistance())
488 return 0;
489
490 if (d<min)
491 min=d;
492 }
493
494 return min;
495}
496
497// --------------------------------------------------------------------------
498//
499// Displays a tooltip
500//
501/*
502void MGMap::ShowToolTip(Int_t px, Int_t py, const char *txt)
503{
504 if (TestBit(kNoToolTips))
505 return;
506
507 Int_t x=0;
508 Int_t y=0;
509
510 const Window_t id1 = gVirtualX->GetWindowID(gPad->GetCanvasID());
511 const Window_t id2 = fToolTip->GetParent()->GetId();
512
513 Window_t id3;
514 gVirtualX->TranslateCoordinates(id1, id2, px, py, x, y, id3);
515
516 // Show tool tip
517 fToolTip->SetText(txt);
518 fToolTip->Show(x+4, y+4);
519}
520*/
521
522// --------------------------------------------------------------------------
523//
524// This function was connected to all created canvases. It is used
525// to redirect GetObjectInfo into our own status bar.
526//
527// The 'connection' is done in Draw. It seems that 'connected'
528// functions must be public.
529//
530/*
531void MGMap::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
532{
533 TVirtualPad *c = (TVirtualPad*)gTQSender; // gTQSender==TCanvas
534
535 gPad = c ? c->GetSelectedPad() : NULL;
536 if (!gPad)
537 return;
538
539 // Try to find a corresponding object with kCannotPick set and
540 // an available TString (for a tool tip)
541 TString str;
542 if (!selected || selected==this)
543 selected = PickObject(px, py, str);
544
545 if (!selected)
546 return;
547
548 // Handle some gui events
549 switch (event)
550 {
551 case kMouseMotion:
552 if (!fToolTip->IsMapped() && !str.IsNull())
553 ShowToolTip(px, py, str);
554 break;
555
556 case kMouseLeave:
557 if (fToolTip->IsMapped())
558 fToolTip->Hide();
559 break;
560
561 default:
562 ExecuteEvent(event, px, py);
563 break;
564 }
565}
566*/
567
568/*
569void MAstroCatalog::RecursiveRemove(TObject *obj)
570{
571 ULong_t hash;
572 Long_t key, val;
573
574 TExMapIter map(&fMapG);
575 while (map.Next(hash, key, val))
576 {
577 if (key != (Long_t)obj)
578 continue;
579
580 fMapG.Remove(hash, key);
581 delete (TObject*)(key);
582 if (val)
583 delete (TString*)(val);
584 break;
585 }
586}
587*/
Note: See TracBrowser for help on using the repository browser.