//------------------------------------------------------------------------------ // gso_Map2D class -- // (C) Piero Giubilato 2008-2010, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "gso_Map2D.cpp" // [Author] "Piero Giubilato" // [Version] "1.5" // [Modified by] "Piero Giubilato" // [Last revision] "04 Aug 2009" // [Language] "C++" // [Compiler] "Visual C++ 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "Source for the gso_Map2D class" // [Key documentation] // "Visual C++ Reference Help" // "Root reference guide" // {Trace} //______________________________________________________________________________ // Standard component #include // Root component #include // Application component #include "global.h" #include "gso_Shaper.h" #include "gso_Map2D.h" // CINT Preprocessor class import definition ClassImp(gso_Map2D) //______________________________________________________________________________ const TGFont* gso_Map2D::text_font_Default = 0; //______________________________________________________________________________ gso_Map2D::gso_Map2D(const TGWindow* window, gso_Palette* pal, UInt_t width, UInt_t height, UInt_t bvl_Size, Float_t bvl_Thick, UInt_t textColor, UInt_t foreColor, UInt_t backColor): gso_Frame(window, width + ruler_Size, height + ruler_Size, bvl_Size, bvl_Thick, gso_Frame::ks_Bevel, foreColor, backColor) { // Default constructor. gso_Map2D provides display functionalities for 2D // data array and structures. While less powerful than the TASImage root // class, it offers maximum speed and multithreading capabilities (soon...). // // 'window' is the container window // 'pal' is the gso_Palette object necessary to the map creation // 'width' is the width of the 2D map in pixels // 'height' is the height of the 2D map in pixels // Debug dbg_Print("gso_Map2D::gso_Map2D:(default)", DBG_LVL_ZERO); // Retrieve a default font fore safety text_font_Default = gClient->GetResourcePool()->GetDefaultFont(); // Sets the ruler graphic context ruler_Font = (gClient->GetFontPool())->GetFont("Arial", -9, 0, 0);; ruler_gc_Set.fMask = kGCFont | kGCForeground | kGCClipMask | kGCClipXOrigin | kGCClipYOrigin; ruler_gc_Set.fFont = text_font_Default->GetFontHandle(); ruler_gc_Set.fForeground = ruler_textColor; ruler_gc_Set.fClipMask = kNone;; ruler_gc_Set.fClipXOrigin = 0; ruler_gc_Set.fClipYOrigin = 0; ruler_gc_Set.fFont = gVirtualX->GetFontHandle((FontStruct_t)ruler_Font->GetFontStruct()); ruler_gc_Hnd = gVirtualX->CreateGC(GetId(), &ruler_gc_Set); // Sets the xor GC xor_Font = (gClient->GetFontPool())->GetFont("Arial", -12, 40, 0); xor_gc_Set.fMask = kGCFont | kGCForeground | kGCLineWidth | kGCLineStyle | kGCFunction | kGCFillStyle | kGCFillRule; xor_gc_Set.fForeground = 0xFFFFFF; xor_gc_Set.fLineWidth = 2; xor_gc_Set.fLineStyle = kLineSolid; xor_gc_Set.fFunction = kGXxor; xor_gc_Set.fFillStyle = kFillSolid; xor_gc_Set.fFillRule = kWindingRule; xor_gc_Set.fFont = gVirtualX->GetFontHandle((FontStruct_t)xor_Font->GetFontStruct()); xor_gc_Hnd = gVirtualX->CreateGC(GetId(), &xor_gc_Set); // Sets the flyer GC flyer_Font = (gClient->GetFontPool())->GetFont("Arial Black", -12, 40, 0); flyer_gc_Set.fMask = kGCFont | kGCBackground | kGCForeground | kGCLineWidth | kGCLineStyle | kGCFunction | kGCFillStyle | kGCFillRule; flyer_gc_Set.fBackground = 0xFFFFFF; flyer_gc_Set.fForeground = 0x000000; flyer_gc_Set.fLineWidth = 1; flyer_gc_Set.fLineStyle = kLineSolid; flyer_gc_Set.fFunction = kGXcopy; flyer_gc_Set.fFillStyle = kFillSolid; flyer_gc_Set.fFillRule = kWindingRule; flyer_gc_Set.fFont = gVirtualX->GetFontHandle((FontStruct_t)flyer_Font->GetFontStruct()); flyer_gc_Hnd = gVirtualX->CreateGC(GetId(), &flyer_gc_Set); // Reset data pointer data_US = 0; data_S = 0; data_UI = 0; data_I = 0; data_F = 0; data_D = 0; data_Mode = kdt_Null; data_Local = 0; // Reset data sizes data_Width = 0; data_Height = 0; // Set the palette range palette = pal; pal_range_Max = 1; pal_range_Min = 0; pal_range_Auto = true; pal_range_Update = false; // Connect the palette events palette->Connect(palette, "pal_Updated()", "gso_Map2D", this, "pal_updated_Do()"); palette->Connect(palette, "mouse_Start(Float_t)", "gso_Map2D", this, "pal_start_Do(Float_t)"); palette->Connect(palette, "mouse_Stop(Float_t)", "gso_Map2D", this, "pal_stop_Do(Float_t)"); palette->Connect(palette, "mouse_Shift(Float_t)", "gso_Map2D", this, "pal_shift_Do(Float_t)"); palette->Connect(palette, "mouse_Scale(Float_t)", "gso_Map2D", this, "pal_scale_Do(Float_t)"); // No ROI roi_Left = 0; roi_Top = 0; roi_Width = 0; roi_Height = 0; roi_Update = false; // Mouse status mouse_start_X = 0; mouse_old_X = 0; mouse_start_Y = 0; mouse_old_Y = 0; mouse_start_B = 0; mouse_old_B = 0; mouse_data_String.Form("Empty"); mouse_curr_Mode = kmm_None; mouse_old_Mode = kmm_None; mouse_data_Mode = kmd_None; mouse_flyer_Map = 0; mouse_flyer_Array = 0; mouse_flyer_oX = 0; mouse_flyer_oY = 0; mouse_flyer_oLeft = 0; mouse_flyer_oTop = 0; mouse_flyer_oWidth = 0; mouse_flyer_oHeight = 0; mouse_flyer_Drawn = false; // Clear the PxMap Id and the frame array img_PxMap = 0; map_Array = new UInt_t[width * height]; map_PxMap = 0; rulH_Array = new UInt_t[(width - ruler_Size) * ruler_Size]; rulH_PxMap = 0; rulV_Array = new UInt_t[ruler_Size * (height - ruler_Size)]; rulV_PxMap = 0; // Enables the events handler AddInput(kButtonPressMask | kButtonReleaseMask); AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask); Connect("ProcessedEvent(Event_t*)", "gso_Map2D", this, "Event(Event_t*)"); // Timer parameters refresh_Timer = new TTimer(1000); refresh_Timer->Connect("Timeout()", "gso_Map2D", this, "data_Refresh()"); // Creates the standard font and clears the label layout(s) lbl_List.clear(); // Set font default color and name SetTextColor(0xabcde0); //textColor SetFont("Arial", -9, 50); // Check for minimum size if (width < 2 * ruler_Size || height < 2 * ruler_Size) { if (width < 2 * ruler_Size) width = 2 * ruler_Size; if (height < 2 * ruler_Size) height = 2 * ruler_Size; Resize(width, height); } } //______________________________________________________________________________ gso_Map2D::~gso_Map2D() { // Default destructor dbg_Print("gso_Map2D::~gso_Map2D:()", DBG_LVL_ZERO); // Removes the graphic contexs gVirtualX->DeleteGC(ruler_gc_Hnd); gVirtualX->DeleteGC(xor_gc_Hnd); gVirtualX->DeleteGC(flyer_gc_Hnd); // Removes the local data copy if (data_Local) delete[] data_Local; // Removes the timer delete refresh_Timer; // Removes the frame array if any if (map_Array) delete[] map_Array; // Removes the PixMaps if any if (map_PxMap) gVirtualX->DeletePixmap(map_PxMap); if (img_PxMap) gVirtualX->DeletePixmap(map_PxMap); if (rulH_PxMap) gVirtualX->DeletePixmap(rulH_PxMap); if (rulV_PxMap) gVirtualX->DeletePixmap(rulV_PxMap); } //______________________________________________________________________________ void gso_Map2D::data_Set(const UShort_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(UShort)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_US = data; data_Mode = kdt_UShort; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const Short_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(Short)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_S = data; data_Mode = kdt_Short; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const UInt_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(UInt)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_UI = data; data_Mode = kdt_UInt; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const Int_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(Int)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_I = data; data_Mode = kdt_Int; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const Float_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(Float)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_F = data; data_Mode = kdt_Float; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const Double_t* data, UInt_t data_Width_t, UInt_t data_Height_t) { // Debug dbg_Print("gso_Map2D::data_Set:(Double)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_D = data; data_Mode = kdt_Double; data_Init(data_Width_t, data_Height_t); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_US = layer->dp_Front(); data_Mode = kdt_UShort; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_S = layer->dp_Front(); data_Mode = kdt_Short; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_UI = layer->dp_Front(); data_Mode = kdt_UInt; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_I = layer->dp_Front(); data_Mode = kdt_Int; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_F = layer->dp_Front(); data_Mode = kdt_Float; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Set(const data_Layer* layer) { // Debug dbg_Print("gso_Map2D::data_Set:(data_Layer*)", DBG_LVL_MAKE); // Save the data reference and sets up the frame data_D = layer->dp_Front(); data_Mode = kdt_Double; data_Init(layer->dp_col_Count(), layer->dp_row_Count()); } //______________________________________________________________________________ void gso_Map2D::data_Init(UInt_t d_Width, UInt_t d_Height) { // Debug dbg_Print("gso_Map2D::data_Init:(UInt, UInt)", DBG_LVL_MAKE); // Assign data dimensions data_Width = d_Width; data_Height = d_Height; // Emits signal data_Changed(); // Reassign local data copy memory (enable if data local copy is used) //if (data_Local) delete[] data_Local; //data_Local = new Double_t[data_Width * data_Height]; } //______________________________________________________________________________ void gso_Map2D::Event(Event_t* evn) { // Handles the mouse events over the map dbg_Print("gso_Map2D::Event:(Event_t*)", DBG_LVL_STEP); // Check for refresh system events if (evn->fType == 9) return; // System calls if (evn->fState > 0xFFFF) return; // This to avoid some wierd behaviours // Codify states bool key_Shift = evn->fState & 1; // Shift bool btn_Left = evn->fState >> 8 & 1; // Left mouse button down bool btn_Right = evn->fState >> 10 & 1; // Right mouse button down // Sets border area size UInt_t brd_Size = ruler_Size + BrdSize(); UInt_t map_mid_X = BrdSize() + (ruler_Size + ClrWidth()) / 2; UInt_t map_mid_Y = BrdSize() + (ruler_Size + ClrHeight()) / 2; // Stores current parameters mouse_curr_X = evn->fX; mouse_curr_Y = evn->fY; // Operates only if the event started in this window // ------------------------------------------------- // Already pressed if (mouse_curr_Mode == kmm_Out) { if (evn->fState == 0) mouse_curr_Mode = kmm_None; else return; } // Exit if (evn->fType == 6 && evn->fState == 0) { mouse_curr_Mode = kmm_Out; return; } // Mouse button driven actions // --------------------------- // Start references on left/right click if (mouse_curr_Mode == kmm_None && (btn_Left || btn_Right)) { // Stores reference position mouse_start_X = evn->fX; mouse_start_Y = evn->fY; mouse_start_B = evn->fState; // Stores reference ROI limits roi_start_Left = roi_Left; roi_start_Top = roi_Top; roi_start_Width = roi_Width; roi_start_Height = roi_Height; // Set the mode as started mouse_curr_Mode = kmm_Start; } // Mode selection start if (mouse_curr_Mode == kmm_Start) { if (mouse_old_B == mouse_start_B && btn_Left) mouse_curr_Mode = kmm_Drag; // Drag if (mouse_old_B == mouse_start_B && btn_Right) mouse_curr_Mode = kmm_Zoom; // Zoom if (mouse_start_B == 256 && evn->fState == 0) { if (evn->fX < brd_Size && evn->fY > (GetHeight() - brd_Size)) { opt_Clicked(); // Right click on the option corner mouse_curr_Mode = kmm_None; // Square } else { mouse_curr_Mode = kmm_Square; // Square } } } // Data show mode start if (mouse_curr_Mode == kmm_Start && mouse_data_Mode == kmd_None) { if (mouse_old_B == 1024 && evn->fState == 0) { mouse_data_Mode = kmd_Point; // Point mouse_curr_Mode = kmm_Data; // Switch to avoid killing the mode } } // Stopping current states // ----------------------- // Stop dragging if (mouse_curr_Mode == kmm_Drag && !btn_Left) mouse_curr_Mode = kmm_None; // Stop zooming if (mouse_curr_Mode == kmm_Zoom && !btn_Right) mouse_curr_Mode = kmm_None; // Stop area selection (with zoom) if (mouse_curr_Mode == kmm_Square && btn_Left) { // Ratio constrain if (key_Shift) evn->fY = mouse_start_Y + (evn->fX - mouse_start_X); // Clear selection mouse_curr_Mode = kmm_None; // Calculates new ROI if (mouse_start_X != evn->fX && mouse_start_Y != evn->fY) { // Calculates new roi Double_t sL, sT, sW, sH; if (evn->fX > mouse_start_X) {sL = mouse_start_X; sW = evn->fX - mouse_start_X;} else {sL = evn->fX; sW = mouse_start_X - evn->fX;}; if (evn->fY > mouse_start_Y) {sT = evn->fY; sH = evn->fY - mouse_start_Y;} else {sT = mouse_start_Y; sH = mouse_start_Y - evn->fY;}; Double_t map_Width = ClrWidth() - ruler_Size; Double_t map_Height = ClrHeight() - ruler_Size; // Checks rulers constrain and calculates the new area if (mouse_start_X > brd_Size + 1) { roi_Left = (Int_t)(roi_Left + ((sL - brd_Size) / map_Width) * roi_Width + 0.5); roi_Width = (Int_t)((sW / map_Width) * roi_Width + 0.5); } if (mouse_start_Y < GetHeight() - brd_Size) { roi_Top = (Int_t)(roi_Top + ((map_Height - sT + BrdSize()) / map_Height) * roi_Height + 0.5); roi_Height = (Int_t)((sH / map_Height) * roi_Height + 0.5); } // Draw Draw(roi_Left, roi_Top, roi_Width, roi_Height); } } // Stop area selection (no zoom) if (mouse_curr_Mode == kmm_Square && btn_Right) { mouse_curr_Mode = kmm_None; gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); } // Stop data mode if (mouse_curr_Mode == kmm_Data) { // Data mode is used just as a first click latch, so // release it to allow following mouse operations mouse_curr_Mode = kmm_None; } else if (mouse_old_Mode == kmm_Start) { if (mouse_data_Mode != kmd_None && mouse_old_B == 1024 && evn->fState == 0) { mouse_curr_Mode = kmm_None; mouse_data_Mode = kmd_None; mouse_flyer_Draw(evn->fX, evn->fY, &mouse_data_String); } } // Mouse motion driven actions // --------------------------- // Data mode on (show values) if (mouse_data_Mode == kmd_Point && mouse_curr_Mode == kmm_None) { // Check for map boundaries if (evn->fX < brd_Size || evn->fX > GetWidth() - BrdSize() | evn->fY < BrdSize() || evn->fY > GetWidth() - brd_Size) { mouse_flyer_Draw(evn->fX, evn->fY, &mouse_data_String); return; } // Retrives data coordinates Double_t dX, dY; if (mouse_to_data_XY(evn->fX, evn->fY, dX, dY)) { if (data_draw_Style == ks_Map) mouse_data_String.Form("(%i, %i) %g", (UInt_t)dX, (UInt_t)dY, data_Value((UInt_t)dX, (UInt_t)dY)); if (data_draw_Style == ks_Plot) mouse_data_String.Form("(%g, %g)", dX, dY); } else { mouse_data_String.Form("(--,--)"); } // Draw the flyer and the crosshair into the data map mouse_flyer_Draw(evn->fX, evn->fY, &mouse_data_String); } // Do square selection if (mouse_curr_Mode == kmm_Square) { // Ratio constrain if (key_Shift) evn->fY = mouse_start_Y + (evn->fX - mouse_start_X); // Changes Y only if (mouse_start_X <= brd_Size + 1) { mouse_start_X = brd_Size + 1; evn->fX = GetWidth() - BrdSize() + 1; } // Changes X only if (mouse_start_Y >= GetHeight() - brd_Size) { mouse_start_Y = GetHeight() - brd_Size; evn->fY = BrdSize() - 1; } // Limit practical area if (evn->fX < brd_Size) evn->fX = brd_Size; if (evn->fY < BrdSize()) evn->fY = BrdSize(); if (evn->fX > GetWidth() - BrdSize() - 1) evn->fX = GetWidth() - BrdSize() - 1; if (evn->fY > GetHeight() - brd_Size - 1) evn->fY = GetHeight() - brd_Size - 1; // Clears previous selection if (mouse_old_Mode == kmm_Square) { gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); } // Draws new selection gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, evn->fX - mouse_start_X, evn->fY - mouse_start_Y); } // Do fluid zooming if (mouse_curr_Mode == kmm_Zoom) { // Calculate zoom factor Float_t zX, zY; // X zoom if (evn->fX >= mouse_start_X) { zX = 50 / (Float_t)(evn->fX - mouse_start_X); if (zX > 1) zX = 1; } else { zX = 1 + (Float_t)(mouse_start_X - evn->fX) / 50; } // Y zoom if (evn->fY >= mouse_start_Y) { zY = 1 + (Float_t)(evn->fY - mouse_start_Y) / 50; } else { zY = 50 / (Float_t)(mouse_start_Y - evn->fY); if (zY > 1) zY = 1; } // Choses which kind of zoom to use if (mouse_start_X <= brd_Size) zX = 1; else if (mouse_start_Y >= GetHeight() - brd_Size) zY = 1; else {zX = (zX + zY) / 2; zY = zX;} // Perform the zoom roi_Left = roi_start_Left - (Int_t)(roi_start_Width * (zX - 1) / 2); roi_Top = roi_start_Top - (Int_t)(roi_start_Height * (zY - 1) / 2); roi_Width = (Int_t)(roi_start_Width * zX); roi_Height = (Int_t)(roi_start_Height * zY); // Draw //if (roi_Left != roi_old_Left || roi_Top != roi_old_Top) { Draw(roi_Left, roi_Top, roi_Width, roi_Height); //} } // Do dragging if (mouse_curr_Mode == kmm_Drag) { // Calculate relative shift Float_t relX = (Float_t)(mouse_start_X - evn->fX) / GetWidth(); Float_t relY = (Float_t)(evn->fY - mouse_start_Y) / GetHeight(); // Check border constrains if (mouse_start_X <= brd_Size) relX = 0; if (mouse_start_Y >= GetHeight() - brd_Size) relY = 0; // Defines new ROI roi_Left = roi_start_Left + (Int_t)(relX * roi_Width); roi_Top = roi_start_Top + (Int_t)(relY * roi_Height); // Draw & release the signal if (roi_Left != roi_old_Left || roi_Top != roi_old_Top) { Draw(roi_Left, roi_Top, roi_Width, roi_Height); } } // Stores mouse values mouse_old_X = evn->fX; mouse_old_Y = evn->fY; mouse_old_B = evn->fState; mouse_old_Mode = mouse_curr_Mode; } // **************** // ** pal events ** // **************** void gso_Map2D::pal_updated_Do() { // Handles the change of palette color dbg_Print("gso_Map2D::pal_updated_Do:()", DBG_LVL_STEP); // Redraw the map data_Refresh(); } //______________________________________________________________________________ void gso_Map2D::pal_start_Do(Float_t pos) { // Handles range shift from the palette dbg_Print("gso_Map2D::pal_start_Do:(Float_t)", DBG_LVL_STEP); // Do this only in map mode! if (data_draw_Style != ks_Map) return; // Stores the actual range and mouse start relative position pal_rs_Min = pal_range_Min; pal_rs_Max = pal_range_Max; pal_rel_Start = pos; } //______________________________________________________________________________ void gso_Map2D::pal_stop_Do(Float_t pos) { // Handles range shift from the palette dbg_Print("gso_Map2D::pal_stop_Do:(Float_t)", DBG_LVL_STEP); // Do this only in map mode! if (data_draw_Style != ks_Map) return; // Stores the actual range and mouse start relative position pal_rel_Stop = pos; // New range Double_t min = floor((1 - pal_rel_Start) * (pal_rs_Max - pal_rs_Min) + pal_rs_Min); Double_t max = floor((1 - pal_rel_Stop) * (pal_rs_Max - pal_rs_Min) + pal_rs_Min); // Set the new range pal_range_Auto = false; range_Set(max, min); } //______________________________________________________________________________ void gso_Map2D::pal_shift_Do(Float_t factor) { // Handles range shift from the palette dbg_Print("gso_Map2D::pal_shifted_Do:(Float_t)", DBG_LVL_STEP); // Do this only in map mode! if (data_draw_Style != ks_Map) return; // Refresh the range Double_t max = floor((pal_rs_Max + 4 * (pal_rs_Max - pal_rs_Min) * factor)); Double_t min = floor((pal_rs_Min + 4 * (pal_rs_Max - pal_rs_Min) * factor)); // Set the new range pal_range_Auto = false; range_Set(max, min); } //______________________________________________________________________________ void gso_Map2D::pal_scale_Do(Float_t factor) { // Handles range shift from the palette dbg_Print("gso_Map2D::pal_scaled_Do:(Float_t)", DBG_LVL_STEP); // Do this only in map mode! if (data_draw_Style != ks_Map) return; // Refresh the range Double_t max = floor((pal_rs_Max + pal_rs_Min) / 2 + (pal_rs_Max - pal_rs_Min) * factor / 2); Double_t min = floor((pal_rs_Max + pal_rs_Min) / 2 - (pal_rs_Max - pal_rs_Min) * factor / 2); // Set the new range pal_range_Auto = false; range_Set(max, min); } // ************* // ** Utility ** // ************* //______________________________________________________________________________ bool gso_Map2D::mouse_to_data_XY(Int_t mX, Int_t mY, Double_t& dX, Double_t& dY) { // Returns data coordinate from mouse coordinates. The function returns // true if the mouse coordinates are into the data area, false otherwise. // Data map real estate Double_t map_Width = ClrWidth() - ruler_Size; Double_t map_Height = ClrHeight() - ruler_Size; Int_t brd_Size = ruler_Size + BrdSize(); Double_t pdX, pdY; // Calculates ROI relative position pdX = (Int_t)(roi_Left + ((Double_t)(mX - brd_Size) / map_Width) * (Double_t)roi_Width); pdY = (Int_t)(roi_Top + ((Double_t)(map_Height - mY + BrdSize()) / map_Height) * (Double_t)roi_Height); // Returns the value accordingly to the data style if (data_draw_Style == ks_Map) { dX = UInt_t(pdX); dY = UInt_t(pdY); if (pdX >= 0 && pdX < data_Width && pdY >= 0 && pdY < data_Height) return true; } else if (data_draw_Style == ks_Plot) { dX = pdX; dY = pdY; return true; } else if (data_draw_Style == ks_Histo) { dX = 0; dY = 0; } else { dX = 0; dY = 0; } // Nothing right... return false; } // ***************************** // ** The big effort: DRAWING ** // ***************************** //______________________________________________________________________________ void gso_Map2D::Draw() { // Full draw Draw(0, 0, data_Width, data_Height); } //______________________________________________________________________________ void gso_Map2D::Draw(Double_t rLeft, Double_t rTop, Double_t rWidth, Double_t rHeight) { // Manages the drawing of the entire clear frame (data, rulers, grid, labels) dbg_Print("gso_Map2D::Draw:(UInt, UInt, UInt, UInt)", DBG_LVL_MAKE); // Check for ROI changes (this will be updated in plot mode in case the auorange is active) roi_Update = false; if (roi_old_Left != rLeft || roi_old_Top != rTop || roi_old_Width != rWidth || roi_old_Height != rHeight) roi_Update = true; // Checks ROI limits if (rWidth <= 0) rWidth = 1; if (rWidth > 1E8) rWidth = 1E8; if (rLeft < -1E8) rLeft = -1E8; if (rLeft > 1E8) rLeft = 1E8; if (rHeight <= 0) rHeight = 1; if (rHeight >= 1E8) rHeight = 1E8; if (rTop < -1E8) rTop = -1E8; if (rTop > 1E8) rTop = 1E8; // Store previous ROI roi_old_Left = rLeft; roi_old_Top = rTop; roi_old_Width = rWidth; roi_old_Height = rHeight; // Confirm ROI roi_Left = rLeft; roi_Top = rTop; roi_Width = rWidth; roi_Height = rHeight; // Creates the UInt arrays // ----------------------- // Note: by using the roi_ var we assume that the ROI could change after // the call to data_Draw, which is true in case of auto rescale of one // of the axis // Computes the data map (this will also rise the range_Updated in case) data_Draw(roi_Left, roi_Top, roi_Width, roi_Height); // Computes the rulers (note, this will access the map_PxMap also) if (roi_Update) ruler_Draw(roi_Left, roi_Top, roi_Width, roi_Height); // Generate the PxMaps // ------------------- // Data if (map_PxMap) gVirtualX->DeletePixmap(map_PxMap); map_PxMap = gVirtualX->CreatePixmapFromData((UChar_t*)map_Array, ClrWidth() - ruler_Size, ClrHeight() - ruler_Size); // Rulers if (roi_Update) { // Removes the old PixMap if any if (rulH_PxMap) gVirtualX->DeletePixmap(rulH_PxMap); if (rulV_PxMap) gVirtualX->DeletePixmap(rulV_PxMap); // Create the map PxMap(s) for the rulers rulH_PxMap = gVirtualX->CreatePixmapFromData((UChar_t*)rulH_Array, ClrWidth() - ruler_Size, ruler_Size); rulV_PxMap = gVirtualX->CreatePixmapFromData((UChar_t*)rulV_Array, ruler_Size, ClrHeight() - ruler_Size); // Add the labels to the PxMap label_Draw(); } // Updates the display // ------------------- // Shows the map and the rulers (in case) DoRedraw_Rulers(); // Paints the rulers PxMaps anyway DoRedraw_Data(); // Paints the data PxMap //if (roi_Update) DoRedraw_Rulers(); // Paints the rulers PxMaps // Emits the relevant signals if (roi_Update) roi_Updated(); if (pal_range_Update) range_Updated(); // OK, ROI and Range are definetely updated now! roi_Update = false; pal_range_Update = false; } //______________________________________________________________________________ void gso_Map2D::data_Draw(Double_t rLeft, Double_t rTop, Double_t rWidth, Double_t rHeight) { // Creates a pxMap representing the data dbg_Print("gso_Map2D::data_Draw:(UInt, UInt, UInt, UInt)", DBG_LVL_MAKE); // Draws the data which appear into the selected ROI if (data_draw_Style == ks_Map) { switch (data_Mode) { case kdt_Null: rtw_Map(data_US, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_UShort: rtw_Map(data_US, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Short: rtw_Map(data_S, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_UInt: rtw_Map(data_UI, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Int: rtw_Map(data_I, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Float: rtw_Map(data_F, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Double: rtw_Map(data_D, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; default: dbg_Print("gso_Map2D::fill: unsupported data type!", DBG_LVL_PLAY); } } // Draws the data which appear into the selected ROI if (data_draw_Style == ks_Plot) { switch (data_Mode) { case kdt_Null: rtw_Plot(data_US, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_UShort: rtw_Plot(data_US, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Short: rtw_Plot(data_S, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_UInt: rtw_Plot(data_UI, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Int: rtw_Plot(data_I, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Float: rtw_Plot(data_F, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; case kdt_Double: rtw_Plot(data_D, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); break; default: dbg_Print("gso_Map2D::fill: unsupported data type!", DBG_LVL_PLAY); } } // This has to be used in case the local data copy is made effective // rtw_Draw(data_Local, data_Width, data_Height, pal_range_Auto, rLeft, rTop, rWidth, rHeight); } //______________________________________________________________________________ void gso_Map2D::data_Image() { // Creates a pxMap representing the whole dataset, not the displayed one dbg_Print("gso_Map2D::data_Image:()", DBG_LVL_MAKE); // Draws the data which appear into the selected ROI if (data_draw_Style == ks_Map) { switch (data_Mode) { case kdt_Null: wdi_Map(data_US, data_Width, data_Height); break; case kdt_UShort: wdi_Map(data_US, data_Width, data_Height); break; case kdt_Short: wdi_Map(data_S, data_Width, data_Height); break; case kdt_UInt: wdi_Map(data_UI, data_Width, data_Height); break; case kdt_Int: wdi_Map(data_I, data_Width, data_Height); break; case kdt_Float: wdi_Map(data_F, data_Width, data_Height); break; case kdt_Double: wdi_Map(data_D, data_Width, data_Height); break; default: dbg_Print("gso_Map2D::data_Image:() unsupported data type!", DBG_LVL_PLAY); } } // Draws the data which appear into the selected ROI if (data_draw_Style == ks_Plot) { switch (data_Mode) { case kdt_Null: wdi_Plot(data_US, data_Width, data_Height); break; case kdt_UShort: wdi_Plot(data_US, data_Width, data_Height); break; case kdt_Short: wdi_Plot(data_S, data_Width, data_Height); break; case kdt_UInt: wdi_Plot(data_UI, data_Width, data_Height); break; case kdt_Int: wdi_Plot(data_I, data_Width, data_Height); break; case kdt_Float: wdi_Plot(data_F, data_Width, data_Height); break; case kdt_Double: wdi_Plot(data_D, data_Width, data_Height); break; default: dbg_Print("gso_Map2D::data_Image:() unsupported data type!", DBG_LVL_PLAY); } } } //______________________________________________________________________________ template void gso_Map2D::rtw_Map(const U* data, UInt_t dW, UInt_t dH, bool dAR, Double_t rL, Double_t rT, Double_t rW, Double_t rH) { // Draw a region of interest from the specified data array into a specified // window inside the frame map dbg_Print("gso_Map2D::rtw_Map:(U* data, Int, Int, bool, ...)", DBG_LVL_MAKE); // The data region of interest is defined by rL, rT, rW, rH // The target window inside the frame is defined by wL, wT, wW, wH // Data and graphic window checks // ------------------------------ // Grab the gloabl output frame dimensions Int_t fW = ClrWidth() - ruler_Size; Int_t fH = ClrHeight() - ruler_Size; Int_t fE = fW * fH; if (fW <= 0 || fH <= 0) return; // Clears the frame for (UInt_t i = 0; i < fE; i++) map_Array[i] = 0; // Basic data and ROI checks if (!data) return; if (rL >= dW || rT >= dH || rW <= 0 || rH <= 0) return; // At first set data boundaries equal to ROI boundaries Int_t drL = (Int_t)rL; Int_t drT = (Int_t)rT; Int_t drW = (Int_t)rW; Int_t drH = (Int_t)rH; // Constrains data boundaries if (drL < 0) drL = 0; if (drL >= dW) drL = dW - 1; if (drT < 0) drT = 0; if (drT >= dH) drT = dH - 1; (rL + rW > dW) ? drW = (Int_t)(dW - drL) : drW = (Int_t)(rL + rW - drL); (rT + rH > dH) ? drH = (Int_t)(dH - drT) : drH = (Int_t)(rT + rH - drT); // Set the window limits Double_t dtfX = (Double_t)fW / (Double_t)rW; Double_t dtfY = (Double_t)fH / (Double_t)rH; Int_t wL = (Int_t)(dtfX * (drL - rL)); Int_t wT = (Int_t)(dtfY * (drT - rT)); Int_t wW = (Int_t)(dtfX * drW); Int_t wH = (Int_t)(dtfY * drH); // Constrains and check window limits if (wL < 0) wL = 0; if (wT < 0) wT = 0; if (wL + wW > fW) wW = fW - wL; if (wT + wH > fH) wH = fH - wT; if (wW < 0 || wH <= 0) return; // Invert window top for Y cartesian flipping wT = fH - wT - wH; // Range check and fit // ----------------------- // Calculates left upper corner starting position for both ROI and WINDOW UInt_t drS = UInt_t(dW * drT + drL); UInt_t drxS = 0; UInt_t wS = UInt_t(fW * wT + wL); UInt_t wxS = 0; // Stores old range Double_t pal_range_max_Old = pal_range_Max; Double_t pal_range_min_Old = pal_range_Min; // Data auto range pre scan //std::cout << "rtw_Map: Y range\n"; if (dAR) { pal_range_Max = (Double_t)data[drS]; pal_range_Min = (Double_t)data[drS]; for (UInt_t drY = 0; drY < drH; drY++) { drxS = drS + drY * dW; for (UInt_t drX = 0; drX < drW; drX++) { if (data[drxS + drX] > pal_range_Max) pal_range_Max = (Double_t)data[drxS + drX]; if (data[drxS + drX] < pal_range_Min) pal_range_Min = (Double_t)data[drxS + drX]; } } // Notify a range change in case if (pal_range_Max != pal_range_max_Old || pal_range_Min != pal_range_min_Old) pal_range_Update = true; } // Range check if (pal_range_Max == pal_range_Min) pal_range_Max = pal_range_Min + 1; // Actual data drawing // ------------------- // Palette const UInt_t* pal_Front = palette->palette_Front(); Double_t pal_Scale = 255 / (pal_range_Max - pal_range_Min); // Set scales factors Double_t wrX = (Double_t)rW / (Double_t)fW; Double_t wrY = (Double_t)rH / (Double_t)fH; U dVal; // Clears the (upper and lower) unused part of the frame //for (UInt_t i = 0; i < wS; i++) map_Array[i] = 0; //for (UInt_t i = (wS + wH * fW); i < fE; i++) map_Array[i] = 0; //Int_t cStop = 0; //std::cout << "Before data drawing\n"; // Put the dROI into the WINDOW (by scanning all the WINDOW and reading the dROI) for (UInt_t wY = 0; wY < wH; wY++) { // Xs starting address wxS = wS + wY * fW; drxS = drS + dW * (UInt_t)(drH - floor(wrY * wY) - 1); // Clears the (left and right) unused part of the frame //cStop = (wxS + fW); if (cStop > fE) cStop = fE; //for (UInt_t i = wxS + wW; i < cStop; i++) map_Array[i] = 0; // Scan the Xs for (UInt_t wX = 0; wX < wW; wX++) { // Relates the current pixel position with the nearest data posiiton dVal = data[drxS + (UInt_t)(wrX * wX)]; // Boundary check in case of no autorange if (!dAR) { if (dVal > pal_range_Max) dVal = (U)pal_range_Max; if (dVal < pal_range_Min) dVal = (U)pal_range_Min; } // Transfers the palette color into the PxMap array. Note how the PxMax array // wants a BGRA 4 bytes arrangement for each pixel, so the palette is made by // a 4 bytes UInt_t where the 4 bytes are stored during the palette building. map_Array[wxS + wX] = pal_Front[(UInt_t)((dVal - pal_range_Min) * pal_Scale)]; } } // Put the fast data gridline in case Double_t wStep_X = 1 / wrX; Double_t wStep_Y = 1 / wrY; // Vertical grid if (wStep_X >= grid_step_Min) { for (Int_t fY = 0; fY < fH; fY += 5) { wxS = (fY * fW); for (Double_t fX = 0; fX < fW; fX += wStep_X) { map_Array[wxS + (Int_t)fX] = grid_Color; } } } // Horizontal grid if (wStep_Y >= grid_step_Min) { for (Double_t fY = 0; fY < fH; fY += wStep_Y) { wxS = (Int_t)(fY) * fW; for (Int_t fX = 0; fX < fW; fX += 5) { map_Array[wxS + fX] = grid_Color; } } } } //______________________________________________________________________________ template void gso_Map2D::wdi_Map(const U* data, UInt_t dW, UInt_t dH) { // Generate an image (PxMap) of the whole data set, based on the current // palette and range settings. The generated map is caled 1:1, i.e. for // each data point we get one pixel dbg_Print("gso_Map2D::wdi_Map:(U* data, Int, Int, bool, ...)", DBG_LVL_MAKE); // Kill previous data map in case if (img_PxMap) gVirtualX->DeletePixmap(img_PxMap); // Allocates the pivot char array UInt_t dT = dW * dH; UInt_t* img_Array = new UInt_t[dT]; U dVal; // Sets the palette const UInt_t* pal_Front = palette->palette_Front(); Double_t pal_Scale = 255 / (pal_range_Max - pal_range_Min); // Popolates the pivot array for (UInt_t i = 0; i < dT; i++) { dVal = data[i]; if (dVal > pal_range_Max) dVal = (U)pal_range_Max; if (dVal < pal_range_Min) dVal = (U)pal_range_Min; // Transfers the palette color into the PxMap array. Note how the PxMax array // wants a BGRA 4 bytes arrangement for each pixel, so the palette is made by // a 4 bytes UInt_t where the 4 bytes are stored during the palette building. img_Array[i] = pal_Front[(UInt_t)((dVal - pal_range_Min) * pal_Scale)]; } // Creates the pixel map img_PxMap = gVirtualX->CreatePixmapFromData((UChar_t*)img_Array, dW, dH); // Delete the pivot char array delete[] img_Array; } //______________________________________________________________________________ template void gso_Map2D::rtw_Plot(const U* data, UInt_t dW, UInt_t dH, bool dAR, Double_t rL, Double_t rT, Double_t rW, Double_t rH) { // Plot a region of interest from the specified data range into a specified // window inside the frame map dbg_Print("gso_Map2D::rtw_Plot:(U* data, Int, Int, bool, ...)", DBG_LVL_MAKE); // The data region of interest is defined by rL, rT, rW, rH // The target window inside the frame is defined by wL, wT, wW, wH // Data and graphic window checks // ------------------------------ // Grab the gloabl output frame dimensions Int_t fW = ClrWidth() - ruler_Size; Int_t fH = ClrHeight() - ruler_Size; Int_t fE = fW * fH; if (fW <= 0 || fH <= 0) return; // Clears the frame for (UInt_t i = 0; i < fE; i++) map_Array[i] = 0; // Basic checks if (!data) return; if (rL >= dW || rW <= 0) return; // At first set data boundaries equal to ROI boundaries Int_t drL = (Int_t)rL; Int_t drT = (Int_t)rT; Int_t drW = (Int_t)rW; Int_t drH = (Int_t)rH; // Sets data boundaries if (drL < 0) drL = 0; if (drL >= dW) drL = dW - 1; (rL + rW > dW) ? drW = (Int_t)(dW - drL) : drW = Int_t(rL + rW - drL); // Check data boundaries if (drW <= 0) return; // Scans the data for Y data range, inside the defined X range only //std::cout << "rtw_Plot: Y range\n"; //std::cout << " dW: " << dW << "\n"; //std::cout << " dH: " << dH << "\n"; //std::cout << " drL: " << drL << "\n"; //std::cout << " drT: " << drT << "\n"; //std::cout << " drW: " << drW << "\n"; //std::cout << " drH: " << drH << "\n"; if (dAR) { Double_t dMax = data[(UInt_t)drL]; Double_t dMin = data[(UInt_t)drL]; // Find min and max in the selected range for (UInt_t dY = 0; dY < dH; dY++) { UInt_t dsX = dY * dW; for (UInt_t dX = drL; dX < drL + drW; dX++) { if ((double)data[dsX + dX] > dMax) dMax = (double)data[dsX + dX]; if ((double)data[dsX + dX] < dMin) dMin = (double)data[dsX + dX]; } } // Adapt the vertical ROI in case if (dMax == dMin) dMax = dMin + 1; if (rT != dMin || rH != (dMax - dMin)) { // Changes the ROI roi_Update = true; rT = dMin; rH = dMax - dMin; // Stores the new ROI roi_Top = (Int_t)rT; roi_Height = (Int_t)rH; } } if (rH <= 0) return; // Set the window limits Double_t dtfX = (Double_t)fW / (Double_t)rW; Double_t dtfY = (Double_t)fH / (Double_t)rH; Int_t wL = (Int_t)(dtfX * (drL - rL)); Int_t wT = (Int_t)(dtfY * (rT)); Int_t wW = (Int_t)(dtfX * drW); Int_t wH = (Int_t)(dtfY * rH); // Constrains and check window limits if (wL < 0) wL = 0; if (wL + wW > fW) wW = fW - wL; if (wW < 0 || wH < 0) return; // Actual data drawing // ------------------- // Set scales factors Double_t wrX = (Double_t)rW / (Double_t)fW; Double_t wrY = (Double_t)rH / (Double_t)fH; //std::cout << "rH: " << rH << ", rT: " << rT << ", wT: " << wT << ", wH: " << wH << "\n"; U dVal; // Draw the plots UInt_t drxS = 0; UInt_t color = 0; Int_t wY = 0; for (UInt_t dY = 0; dY < dH; dY++) { // Get the plot color color = palette->color_Get(dY); // Xs starting address drxS = dW * dY; // Very easy // Scan the Xs for (UInt_t wX = 0; wX < wW; wX++) { // Relates the current pixel position with the nearest data posiiton dVal = data[drxS + (UInt_t)(drL + wrX * wX)]; //std::cout << wX << ", " << (UInt_t)(drL + wrX * wX) << ", " << dVal << "\n"; // Calculate frame coordinates wY = fH - ((UInt_t)(dVal / wrY) - wT); if (wY >= 0 && wY < fH) map_Array[fW * wY + wL + wX] = color; //std::cout << (UInt_t)(dVal / wrY) << "\n"; } } // Put the fast data gridline in case Double_t wStep_X = 1 / wrX; Double_t wStep_Y = 1 / wrY; UInt_t wxS = 0; // Vertical grid if (wStep_X >= grid_step_Min) { for (Int_t fY = 0; fY < fH; fY += 5) { wxS = (fY * fW); for (Double_t fX = 0; fX < fW; fX += wStep_X) { map_Array[wxS + (Int_t)fX] = grid_Color; } } } // Horizontal grid if (wStep_Y >= grid_step_Min) { for (Double_t fY = 0; fY < fH; fY += wStep_Y) { wxS = (Int_t)(fY) * fW; for (Int_t fX = 0; fX < fW; fX += 5) { map_Array[wxS + fX] = grid_Color; } } } } //______________________________________________________________________________ template void gso_Map2D::wdi_Plot(const U* data, UInt_t dW, UInt_t dH) { // Generate an image (PxMap) of the whole data set, based on the current // palette and range settings. The generated map is caled 1:1, i.e. for // each data point we get one pixel dbg_Print("gso_Map2D::wdi_Map:(U* data, UInt, UInt)", DBG_LVL_MAKE); } //______________________________________________________________________________ void gso_Map2D::ruler_Draw(Double_t rL, Double_t rT, Double_t rW, Double_t rH) { // Draw rulers tickmarks plus a grid over the frame dbg_Print("gso_Map2D::ruler_Draw:(Int, Int, Int, Int)", DBG_LVL_MAKE); // Frame size UInt_t fW = ClrWidth() - ruler_Size; UInt_t fH = ClrHeight() - ruler_Size; if (fW == 0 || fH == 0) return; // Reproduction ratio Double_t wrX = (Double_t)rW / (Double_t)fW; Double_t wrY = (Double_t)rH / (Double_t)fH; // X axis parameters Int_t dStep_X = 1, dStep_maj_X = 1; Int_t dOff_X = 0; Double_t wOff_X; Double_t wStep_X = (dStep_X / wrX); while (wStep_X < ruler_maj_step_Min) wStep_X = (dStep_maj_X *= 2) / wrX; wStep_X = (dStep_X / wrX); while (wStep_X < ruler_min_step_Min) wStep_X = (dStep_X *= 2) / wrX; if (rL <= 0) dOff_X = -((Int_t)rL % dStep_X); else dOff_X = (dStep_X - ((Int_t)rL % dStep_X)) % dStep_X; wOff_X = (Double_t)dOff_X / wrX; dOff_X += (Int_t)rL; // Y axis parameters Int_t dStep_Y = 1, dStep_maj_Y = 1; Int_t dOff_Y = 0; Double_t wOff_Y; Double_t wStep_Y = (dStep_Y / wrY); while (wStep_Y < ruler_maj_step_Min) wStep_Y = (dStep_maj_Y *= 2) / wrY; wStep_Y = (dStep_Y / wrY); while (wStep_Y < ruler_min_step_Min) wStep_Y = (dStep_Y *= 2) / wrY; if (rT <= 0) dOff_Y = -((Int_t)rT % dStep_Y); else dOff_Y = (dStep_Y - ((Int_t)rT % dStep_Y)) % dStep_Y; wOff_Y = (Double_t)dOff_Y / wrY; dOff_Y += (Int_t)rT; // Clears the rulers for (UInt_t i = 0; i < ruler_Size * fW; i++) rulH_Array[i] = ruler_backColor; for (UInt_t i = 0; i < ruler_Size * fH; i++) rulV_Array[i] = ruler_backColor; // Clears Labels lbl_List.clear(); lbl_Item label; // Pivot struct // Pivots UInt_t tick_Size; // Horizontal major ruler for (Double_t fX = wOff_X; fX < fW; fX += wStep_X) { // Major if (dOff_X % (dStep_maj_X) == 0) { // Marker tick_Size = ruler_maj_tick_Size; // Stores label information label.text.Form("%i", dOff_X); label.left = (Int_t)fX + 2; label.top = ruler_maj_tick_Size + 2; label.side = 0; lbl_List.push_back(label); // Minor marker } else tick_Size = ruler_min_tick_Size; // Draw tick for (UInt_t fY = 0; fY < tick_Size; fY++) rulH_Array[(Int_t)fX + fY * fW] = ruler_textColor; // Data step dOff_X += dStep_X; } // Vertical ruler UInt_t wxS, gxS; for (Double_t fY = fH - wOff_Y - 1; fY > 0; fY-=wStep_Y) { // Common start wxS = (UInt_t)(fY) * ruler_Size; gxS = (UInt_t)(fY) * fW; // Major if (dOff_Y % (dStep_maj_Y) == 0) { // Stores label information label.text.Form("%i", dOff_Y); label.left = 2; //ruler_Size - ruler_maj_tick_Size; label.top = (Int_t)fY - 4; label.side = 1; lbl_List.push_back(label); // Axis ticks tick_Size = ruler_maj_tick_Size;; // Minor marker } else tick_Size = ruler_min_tick_Size; // Draw the tick for (UInt_t fX = ruler_Size - tick_Size; fX < ruler_Size; fX++) rulV_Array[wxS + fX] = ruler_textColor; // Data step dOff_Y += dStep_Y; } } //______________________________________________________________________________ void gso_Map2D::label_Draw() { // Draw rulers tickmarks plus a grid over the frame dbg_Print("gso_Map2D::label_Draw:()", DBG_LVL_MAKE); // Check i a font has been defined if (!ruler_Font) return; // Draws the label over the existent PXmaps for (UInt_t i = 0; i < lbl_List.size(); i++) { // Draw the text! if (lbl_List[i].side == 0) { ruler_Font->DrawChars(rulH_PxMap, ruler_gc_Hnd, lbl_List[i].text.Data(), lbl_List[i].text.Length(), lbl_List[i].left, lbl_List[i].top); } else { ruler_Font->DrawChars(rulV_PxMap, ruler_gc_Hnd, lbl_List[i].text.Data(), lbl_List[i].text.Length(), lbl_List[i].left, lbl_List[i].top); } } } //______________________________________________________________________________ void gso_Map2D::mouse_flyer_Draw(Int_t mLeft, Int_t mTop, TString* str) { // Creates a flyer pixmap containing the string dbg_Print("gso_Map2D::flyer_Draw:()", DBG_LVL_MAKE); // Fixed frame references Int_t bvl_Size = BrdSize(); Int_t brd_Size = bvl_Size + ruler_Size; // Pivots UInt_t tB = 3; UInt_t tW = flyer_Font->TextWidth(str->Data(), str->Length()); UInt_t tH = (flyer_Font->TextHeight()); UInt_t fW = tW + 2 * tB; UInt_t fH = tH + 2 * tB; // Frame boundaries check if (mLeft < brd_Size + 1) mLeft = brd_Size + 1; if (mTop < bvl_Size + 1) mTop = bvl_Size + 1; if (mLeft > GetWidth() - bvl_Size - 1) mLeft = GetWidth() - bvl_Size - 1; if (mTop > GetHeight() - brd_Size - 1) mTop = GetHeight() - brd_Size - 1; // Clear previous if (mouse_flyer_Drawn) { // Clear the crosshair gVirtualX->DrawLine(GetId(), xor_gc_Hnd, mouse_flyer_oX, bvl_Size, mouse_flyer_oX, GetHeight() - bvl_Size); gVirtualX->DrawLine(GetId(), xor_gc_Hnd, bvl_Size, mouse_flyer_oY, GetWidth() - bvl_Size, mouse_flyer_oY); // Clear the old flyer gVirtualX->CopyArea(map_PxMap, GetId(), GetGC(), mouse_flyer_oLeft - brd_Size, mouse_flyer_oTop - bvl_Size, // Source mouse_flyer_oWidth + 1, mouse_flyer_oHeight + 1, // Rectangle mouse_flyer_oLeft, mouse_flyer_oTop); // Destination // Reset the flag mouse_flyer_Drawn = false; } // From here we are drawing the new items // If data mode has closed, just exit if (mouse_data_Mode == kmd_None) return; // The crosshair gVirtualX->DrawLine(GetId(), xor_gc_Hnd, mLeft, bvl_Size, mLeft, GetHeight() - bvl_Size); gVirtualX->DrawLine(GetId(), xor_gc_Hnd, bvl_Size, mTop, GetWidth() - bvl_Size, mTop); // Update flyer position respect to the cursor Int_t fLeft = mLeft; Int_t fTop = mTop; (mLeft + fW + 6 < GetWidth() - BrdSize()) ? fLeft += 6 : fLeft = GetWidth() - BrdSize() - fW - 6; (mTop + fH + 12 < GetHeight() - BrdSize() - ruler_Size) ? fTop += 12 : fTop = GetHeight() - BrdSize() - ruler_Size - fH - 12; if (fLeft < 0) fLeft = 0; if (fTop < 0) fTop = 0; if (fLeft < BrdSize() + ruler_Size) fLeft = BrdSize() + ruler_Size; if (fTop < BrdSize()) fTop = BrdSize(); // White back flyer_gc_Set.fMask = kGCForeground; flyer_gc_Set.fForeground = 0xFFFFFF; gVirtualX->ChangeGC(flyer_gc_Hnd, &flyer_gc_Set); gVirtualX->FillRectangle(GetId(), flyer_gc_Hnd, fLeft, fTop, fW, fH); // Graded border flyer_gc_Set.fForeground = 0xCCCCCC; gVirtualX->ChangeGC(flyer_gc_Hnd, &flyer_gc_Set); gVirtualX->DrawRectangle(GetId(), flyer_gc_Hnd, fLeft, fTop, fW, fH); flyer_gc_Set.fForeground = 0xDDDDDD; gVirtualX->ChangeGC(flyer_gc_Hnd, &flyer_gc_Set); gVirtualX->DrawRectangle(GetId(), flyer_gc_Hnd, fLeft + 1, fTop + 1, fW - 2, fH - 2); // Text flyer_gc_Set.fForeground = 0x000000; gVirtualX->ChangeGC(flyer_gc_Hnd, &flyer_gc_Set); flyer_Font->DrawChars(GetId(), flyer_gc_Hnd, str->Data(), str->Length(), fLeft + tB, fTop + tH); // Stores the now old position and size of the flyer mouse_flyer_Drawn = true; mouse_flyer_oX = mLeft; mouse_flyer_oY = mTop; mouse_flyer_oLeft = fLeft; mouse_flyer_oTop = fTop; mouse_flyer_oWidth = fW; mouse_flyer_oHeight = fH; } //______________________________________________________________________________ void gso_Map2D::range_Set(Double_t max, Double_t min) { // Sets the range (paalette for the map, Y axis for the others plots) dbg_Print("gso_Map2D::range_Set:(Double, Double)", DBG_LVL_FLOW); // Sets range limits if (min <= max) {pal_range_Min = min; pal_range_Max = max;} else {pal_range_Max = min; pal_range_Min = max;} // Redraw the map data_Refresh(); // Emits the range updated signal range_Updated(); } //______________________________________________________________________________ void gso_Map2D::range_Get(const Double_t* max, const Double_t* min) const { // Returns the palette range dbg_Print("gso_Map2D::range_get:(Double, Double)", DBG_LVL_FLOW); // Sets range limits max = &pal_range_Max; min = &pal_range_Min; } //______________________________________________________________________________ Double_t gso_Map2D::range_Max() const { // Returns the palette range maximum dbg_Print("gso_Map2D::range_Max:()", DBG_LVL_FLOW); return pal_range_Max; } //______________________________________________________________________________ Double_t gso_Map2D::range_Min() const { // Returns the palette range minimum dbg_Print("gso_Map2D::range_Min:()", DBG_LVL_FLOW); return pal_range_Min; } //______________________________________________________________________________ void gso_Map2D::range_Max(Double_t max) { // sets the palette range maximum dbg_Print("gso_Map2D::range_Max:(Double)", DBG_LVL_FLOW); range_Set(max, pal_range_Min); } //______________________________________________________________________________ void gso_Map2D::range_Min(Double_t min) { // Sets the palette range minimum dbg_Print("gso_Map2D::range_Min:(Double)", DBG_LVL_FLOW); range_Set(pal_range_Max, min); } //______________________________________________________________________________ bool gso_Map2D::range_Auto() const { // Returns the palette range minimum dbg_Print("gso_Map2D::range_Auto:()", DBG_LVL_FLOW); return pal_range_Auto; } //______________________________________________________________________________ void gso_Map2D::range_Auto(bool automatic) { // Sets the palette range auto mode dbg_Print("gso_Map2D::range_Auto:(bool)", DBG_LVL_FLOW); pal_range_Auto = automatic; // Refreshes in case if (automatic) data_Refresh(); else range_Updated(); } //______________________________________________________________________________ const Pixmap_t gso_Map2D::data_PxMap(bool whole) { // Returns the handle to the displayed image, or to // the virtual data image if whole is set to true dbg_Print("gso_Map2D::data_PxMap:()", DBG_LVL_MAKE); // Returns if (whole) { data_Image(); // Generate the image map return img_PxMap; } else { return map_PxMap; } } //______________________________________________________________________________ void gso_Map2D::data_Style(UInt_t dStyle) { // Set the data drawing style dbg_Print("gso_Map2D::data_Style:(UInt)", DBG_LVL_MAKE); // Set the data style data_draw_Style = dStyle; // Refresh data_Refresh(); // Emit a signal style_Updated(); } //______________________________________________________________________________ void gso_Map2D::data_Copy() { // Make a local copy of the data dbg_Print("gso_Map2D::data_Copy:()", DBG_LVL_MAKE); // Copy the data to the common double array switch (data_Mode) { case kdt_UShort: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_US[i]; break; case kdt_Short: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_S[i]; break; case kdt_UInt: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_UI[i]; break; case kdt_Int: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_I[i]; break; case kdt_Float: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_F[i]; break; case kdt_Double: for (UInt_t i = 0; i < data_Width * data_Height; i++) data_Local[i] = data_D[i]; break; } } //______________________________________________________________________________ void gso_Map2D::data_Refresh() { // Refresh the map with full data, using the present ROI data_Refresh(roi_Left, roi_Top, roi_Width, roi_Height); } //______________________________________________________________________________ void gso_Map2D::data_Refresh(Double_t r_Left, Double_t r_Top, Double_t r_Width, Double_t r_Height) { // Reloads data and fit them into the new ROI dbg_Print("gso_Map2D::data_Refresh:(UInt rL, rT, rW, rH)", DBG_LVL_FLOW); // Check if (data_Mode == kdt_Null) return; // Saves the ROI roi_Left = r_Left; roi_Width = r_Width; switch (data_draw_Style) { case ks_Map: roi_Top = r_Top; roi_Height = r_Height; break; case ks_Plot: if (!pal_range_Auto) { roi_Top = r_Top; roi_Height = r_Height; } break; default: break; } // Reload the data (to be used in case...) // data_Copy(); // Redraw the map Draw(roi_Left, roi_Top, roi_Width, roi_Height); // Emits signal data_Updated(); } //______________________________________________________________________________ void gso_Map2D::data_Refresh(bool x_Fit, bool y_Fit, bool oto_Fit, bool px_Fit) { // Reloads data, and change the ROI to fit them // x_Fit will fit the ROI to the data width // y_Fit will fit the ROI to the data height // oto_Fit will force a one-to-one aspect ratio // px_Fit will force a 1:1 pixel to data scale dbg_Print("gso_Map2D::data_Refresh:(bool bool)", DBG_LVL_FLOW); // Check if (data_Mode == kdt_Null) return; // Fits the ROY for the X axis if (x_Fit) { roi_Left = 0; roi_Width = data_Width; } // Fits the ROY for the Y axis if (y_Fit) { roi_Top = 0; roi_Height = data_Height; } // 1 to 1 aspect ratio if (oto_Fit) { (roi_Width >= roi_Height) ? roi_Height = roi_Width : roi_Width = roi_Height; } // 1 to 1 pixel to data scale if (px_Fit) { roi_Width = ClrWidth() - ruler_Size; roi_Height = ClrHeight() - ruler_Size; } // Reload the data (to be used in case...) // data_Copy(); // Redraw the map bool pal_range_Old = pal_range_Auto; switch (data_draw_Style) { case ks_Map: Draw(roi_Left, roi_Top, roi_Width, roi_Height); break; case ks_Plot: if (y_Fit) pal_range_Auto = true; Draw(roi_Left, roi_Top, roi_Width, roi_Height); pal_range_Auto = pal_range_Old; break; default: break; } // Emits signal data_Updated(); } //______________________________________________________________________________ void gso_Map2D::data_refresh_Auto(UInt_t interval) { // Enable/disable timer refresh_Timer->SetTime(interval); refresh_Timer->Reset(); (interval > 10) ? refresh_Timer->TurnOn() : refresh_Timer->TurnOff(); } //______________________________________________________________________________ Double_t gso_Map2D::data_Value(UInt_t x, UInt_t y) const { // Retrieves one data point from the linked array dbg_Print("gso_Map2D::data_Value:(UInt, UInt)", DBG_LVL_FLOW); // Check boundaries if (x > data_Width) return 0; if (y > data_Height) return 0; // Returns whatever kind of data as double switch (data_Mode) { case kdt_UShort: return (Double_t)data_US [y * data_Width + x]; break; case kdt_Short: return (Double_t)data_S [y * data_Width + x]; break; case kdt_UInt: return (Double_t)data_UI [y * data_Width + x]; break; case kdt_Int: return (Double_t)data_I [y * data_Width + x]; break; case kdt_Float: return (Double_t)data_F [y * data_Width + x]; break; case kdt_Double: return (Double_t)data_D [y * data_Width + x]; break; } // Something wrong return 0; } //______________________________________________________________________________ void gso_Map2D::MoveResize(Int_t left, Int_t top, UInt_t width, UInt_t height) { // Move and resize the mpas dbg_Print("gso_Map2D::MoveResize:(Int, Int, UInt, UInt)", DBG_LVL_FLOW); // Redraw the parent frame gso_Frame::MoveResize(left, top, width, height); // The map needs to be redrawn with the new dimensions Draw(); } //______________________________________________________________________________ void gso_Map2D::Resize(UInt_t width, UInt_t height) { // Move and resize the mpas dbg_Print("gso_Map2D::Resize:(UInt, UInt)", DBG_LVL_FLOW); // Redraw the parent frame gso_Frame::Resize(width, height); // Delete the previous map array if (map_Array) delete []map_Array; map_Array = new UInt_t[(ClrWidth() - ruler_Size) * (ClrHeight() - ruler_Size)]; // Rulers if (rulH_Array) delete []rulH_Array; rulH_Array = new UInt_t[(ClrWidth() - ruler_Size) * ruler_Size]; if (rulV_Array) delete []rulV_Array; rulV_Array = new UInt_t[ruler_Size * (ClrHeight() - ruler_Size)]; // The map needs to be redrwan with the new dimensions Draw(); } //______________________________________________________________________________ void gso_Map2D::DoRedraw() { // Draws the current map to the palette frame. This function // overloads the TGFrame original one. dbg_Print("gso_Map2D::DoRedraw:()", DBG_LVL_FLOW); // Redraws the base frame gso_Frame::DoRedraw(); // Redraws the map if any available DoRedraw_Data(); // Redraw the rulers DoRedraw_Rulers(); } //______________________________________________________________________________ void gso_Map2D::DoRedraw_Data() { // Redraws the map if (map_PxMap) { gVirtualX->CopyArea(map_PxMap, GetId(), GetGC(), 0, 0, ClrWidth() - ruler_Size, ClrHeight() - ruler_Size, ClrLeft() + ruler_Size, ClrTop()); } // Redraws the mouse flyer in case mouse_flyer_Drawn = false; if (mouse_curr_Mode == kmm_None && mouse_data_Mode != kmd_None) { mouse_flyer_Draw(mouse_curr_X, mouse_curr_Y, &mouse_data_String); } // Redraws the current selection in case if (mouse_curr_Mode == kmm_Square) { gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); } } //______________________________________________________________________________ void gso_Map2D::DoRedraw_Rulers() { // Redraws H ruler if (rulH_PxMap) gVirtualX->CopyArea(rulH_PxMap, GetId(), GetGC(), 0, 0, ClrWidth() - ruler_Size, ruler_Size, ClrLeft() + ruler_Size, ClrTop() + ClrHeight() - ruler_Size); // Redraws V ruler if (rulV_PxMap) gVirtualX->CopyArea(rulV_PxMap, GetId(), GetGC(), 0, 0, ruler_Size, ClrHeight() - ruler_Size, ClrLeft(), ClrTop()); } //______________________________________________________________________________ void gso_Map2D::SetFont(const char* fontName, Int_t size, Int_t weight, Int_t slant) { // This function overloads the TGFrame original one. It tryes to retrieve // the specified font, and set it into the text drawing graphic context dbg_Print("gso_Map2D::SetFont:(const char*, Int, Int)", DBG_LVL_STEP); // Set up a font ruler_Font = (gClient->GetFontPool())->GetFont(fontName, size, weight, slant); FontH_t font_Hnd = gVirtualX->GetFontHandle((FontStruct_t)ruler_Font->GetFontStruct()); if (font_Hnd) { ruler_gc_Set.fFont = font_Hnd; ruler_gc_Set.fMask = kGCFont; gVirtualX->ChangeGC(ruler_gc_Hnd, &ruler_gc_Set); } } //______________________________________________________________________________ void gso_Map2D::SetFont(const char* fontName, Bool_t global) { // This function overloads the TGFrame original one. dbg_Print("gso_Map2D::SetFont:(const char*, bool)", DBG_LVL_STEP); // Redirect SetFont(fontName, -12, 0, 0); } //______________________________________________________________________________ void gso_Map2D::SetFont(FontStruct_t font_Str, Bool_t global) { // Changes text font. dbg_Print("gso_Map2D::SetFont:(FontStruct, bool)", DBG_LVL_STEP); // Change it! FontH_t font_Hnd = gVirtualX->GetFontHandle(font_Str); if (font_Hnd) { ruler_gc_Set.fFont = font_Hnd; ruler_gc_Set.fMask = kGCFont; gVirtualX->ChangeGC(ruler_gc_Hnd, &ruler_gc_Set); } } //______________________________________________________________________________ void gso_Map2D::SetTextColor(Pixel_t color) { // This function overloads the TGFrame original one. dbg_Print("gso_Map2D::SetTextColor:(UInt)", DBG_LVL_STEP); // Changes text color ruler_gc_Set.fForeground = color; ruler_gc_Set.fMask = kGCForeground; gVirtualX->ChangeGC(ruler_gc_Hnd, &ruler_gc_Set); }