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

Last change on this file since 4058 was 4058, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 13.4 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 = 100) : 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//
219Int_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. The TObject must be a TLine.
237// Currently only solid and non sloid line are supported.
238//
239void MGMap::DrawLine(TObject *o, unsigned char *buf, int w, int h, Double_t scale)
240{
241 TLine *l = dynamic_cast<TLine*>(o);
242 if (!l)
243 return;
244
245 Double_t x1 = 0.5*w-(l->GetX1()/scale);
246 Double_t x2 = 0.5*w-(l->GetX2()/scale);
247 Double_t y1 = 0.5*h-(l->GetY1()/scale);
248 Double_t y2 = 0.5*h-(l->GetY2()/scale);
249
250 Double_t len = TMath::Hypot(x2-x1, y2-y1);
251
252 Double_t x = x1;
253 Double_t y = y1;
254
255 Int_t step = l->GetLineStyle()==kSolid?1:3;
256
257 Double_t dx = (x2-x1)/len*step;
258 Double_t dy = (y2-y1)/len*step;
259
260 for (int i=0; i<len; i+=step)
261 {
262 x+= dx;
263 y+= dy;
264
265 if (x<0 || y<0 || x>w-1 || y>h-1)
266 continue;
267
268 buf[(int)x+(int)y*w] = Color(l->GetLineColor());
269 }
270}
271
272// --------------------------------------------------------------------------
273//
274// Draw marker into the buffer. The TObject must be a TMarker.
275// Currently kCircle, kMultiply and KDot are supported.
276//
277void MGMap::DrawMarker(TObject *o, unsigned char *buf, int w, int h, Double_t scale)
278{
279 TMarker *m = dynamic_cast<TMarker*>(o);
280 if (!m)
281 return;
282
283 Double_t x = 0.5*w-(m->GetX()/scale);
284 Double_t y = 0.5*h-(m->GetY()/scale);
285
286 Int_t col = Color(m->GetMarkerColor());
287
288 switch (m->GetMarkerStyle())
289 {
290 case kCircle:
291 {
292 Int_t step = 32;
293
294 const Float_t l = (m->GetMarkerSize()*2)+1;
295 for (int i=0; i<step; i++)
296 {
297 const Double_t angle = i*TMath::TwoPi()/step;
298
299 const Double_t x1 = x+l*cos(angle);
300 const Double_t y1 = y+l*sin(angle);
301
302 if (x1<0 || y1<0 || x1>w-1 || y1>h-1)
303 continue;
304
305 buf[(int)x1+(int)y1*w] = col;
306 }
307 }
308 break;
309 case kDot:
310 if (x>=0 && y>=0 && x<w && y<h)
311 buf[(int)x+(int)y*w] = col;
312 break;
313
314 case kMultiply:
315 {
316 const Int_t l = (int)(m->GetMarkerSize()+1);
317
318 for (int i=-l; i<l+1; i++)
319 {
320 Double_t x1 = x+i;
321 Double_t y1 = y+i;
322 if (x1>=0 && y>=0 && x1<w && y<h)
323 buf[(int)x1+(int)y*w] = col;
324 if (x>=0 && y1>=0 && x<w && y1<h)
325 buf[(int)x+(int)y1*w] = col;
326 }
327 }
328 break;
329
330 }
331}
332
333// --------------------------------------------------------------------------
334//
335// Paint all elements to the pad by calling their Paint() function
336//
337void MGMap::Paint(Option_t *o="")
338{
339 Long_t key, val;
340 TExMapIter map(this);
341 while (map.Next(key, val))
342 ((TObject*)key)->Paint();
343}
344
345// --------------------------------------------------------------------------
346//
347// Paint all objects into a buffer of w*h unsigned chars. The scale
348// gives you the conversio factor to convert pad coordinates into
349// buffer pixels - it is the distance from the center of the buffer
350// to one of its edges.
351//
352void MGMap::Paint(unsigned char *buf, int w, int h, Float_t scale)
353{
354 scale /= TMath::Hypot((float)w, (float)h)/2;
355
356 Long_t key, val;
357 TExMapIter map(this);
358 while (map.Next(key, val))
359 {
360 TObject *o = (TObject*)key;
361 DrawLine(o, buf, w, h, scale);
362 DrawMarker(o, buf, w, h, scale);
363 }
364}
365
366// --------------------------------------------------------------------------
367//
368// Search for an object at px, py. Return the pointer to it
369// if found. Set str accordingly if a corresponding TString is found.
370//
371TObject *MGMap::PickObject(Int_t px, Int_t py, TString &str) const
372{
373 Long_t key, val;
374 TExMapIter map(this);
375 while (map.Next(key, val))
376 {
377 if (!val)
378 continue;
379
380 TObject *o=(TObject*)key;
381 if (o->DistancetoPrimitive(px, py)>TPad::GetMaxPickDistance())
382 continue;
383
384 str = *(TString*)val;
385 return o;
386 }
387 return NULL;
388}
389
390// ------------------------------------------------------------------------
391//
392// Returns string containing info about the object at position (px,py).
393// Returned string will be re-used (lock in MT environment).
394// The text will be truncated to 128 charcters
395//
396char *MGMap::GetObjectInfo(Int_t px, Int_t py) const
397{
398 TString str;
399 PickObject(px, py, str);
400
401 static char txt[129];
402 txt[128]=0;
403
404 return strncpy(txt, str.Data(), 128);
405}
406
407// --------------------------------------------------------------------------
408//
409// Calculate distance to primitive by checking all gui elements
410//
411Int_t MGMap::DistancetoPrimitive(Int_t px, Int_t py)
412{
413 Int_t min = INT_MAX;
414
415 Long_t key, val;
416 TExMapIter map(this);
417 while (map.Next(key, val))
418 {
419 TObject *o=(TObject*)key;
420
421 const Int_t d = o->DistancetoPrimitive(px, py);
422
423 if (d<TPad::GetMaxPickDistance())
424 return 0;
425
426 if (d<min)
427 min=d;
428 }
429
430 return min;
431}
432
433// --------------------------------------------------------------------------
434//
435// Displays a tooltip
436//
437/*
438void MGMap::ShowToolTip(Int_t px, Int_t py, const char *txt)
439{
440 if (TestBit(kNoToolTips))
441 return;
442
443 Int_t x=0;
444 Int_t y=0;
445
446 const Window_t id1 = gVirtualX->GetWindowID(gPad->GetCanvasID());
447 const Window_t id2 = fToolTip->GetParent()->GetId();
448
449 Window_t id3;
450 gVirtualX->TranslateCoordinates(id1, id2, px, py, x, y, id3);
451
452 // Show tool tip
453 fToolTip->SetText(txt);
454 fToolTip->Show(x+4, y+4);
455}
456*/
457
458// --------------------------------------------------------------------------
459//
460// This function was connected to all created canvases. It is used
461// to redirect GetObjectInfo into our own status bar.
462//
463// The 'connection' is done in Draw. It seems that 'connected'
464// functions must be public.
465//
466/*
467void MGMap::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
468{
469 TVirtualPad *c = (TVirtualPad*)gTQSender; // gTQSender==TCanvas
470
471 gPad = c ? c->GetSelectedPad() : NULL;
472 if (!gPad)
473 return;
474
475 // Try to find a corresponding object with kCannotPick set and
476 // an available TString (for a tool tip)
477 TString str;
478 if (!selected || selected==this)
479 selected = PickObject(px, py, str);
480
481 if (!selected)
482 return;
483
484 // Handle some gui events
485 switch (event)
486 {
487 case kMouseMotion:
488 if (!fToolTip->IsMapped() && !str.IsNull())
489 ShowToolTip(px, py, str);
490 break;
491
492 case kMouseLeave:
493 if (fToolTip->IsMapped())
494 fToolTip->Hide();
495 break;
496
497 default:
498 ExecuteEvent(event, px, py);
499 break;
500 }
501}
502*/
503
504/*
505void MAstroCatalog::RecursiveRemove(TObject *obj)
506{
507 ULong_t hash;
508 Long_t key, val;
509
510 TExMapIter map(&fMapG);
511 while (map.Next(hash, key, val))
512 {
513 if (key != (Long_t)obj)
514 continue;
515
516 fMapG.Remove(hash, key);
517 delete (TObject*)(key);
518 if (val)
519 delete (TString*)(val);
520 break;
521 }
522}
523*/
Note: See TracBrowser for help on using the repository browser.