GRAHI Documentation Project (GDP)
Filename: SelectMap__define.pro
CLASSNAME: SelectMap
AUTHOR: 
       Antonio Santiago Perez <santiago@grahi.upc.edu>
                              (http://asantiago.gentelibre.org)
DESCRIPTION: 
       Show a background image and make line selection. The
       coordenates of initial/final points of the line seleccion are
       returned normalized respect widget and image size.
METHODS:
HISTORY:
       Mon Nov 15 17:44:54 2004, Antonio Santiago
       <santiago@grahi.upc.edu>
+Code:
PRO SelectMap__define
    
    struct = { SelectMap, $
      INHERITS EventAction, $
      parent_id: 0L, $          ;Parent widget
      base_id: 0L, $            ;WIDGET_BASE of the object.
      widget_id: 0L, $          ;WIDGET_DRAW inside widget_base.
      
      oWindow: OBJ_NEW(), $     ;The window
      oView: OBJ_NEW(), $       ;The view
      oModel: OBJ_NEW(), $      ;The model
      
      oImage: OBJ_NEW(), $      ;Background image
      oPalette: OBJ_NEW(), $    ;Palette for the image
      oSelectLine: OBJ_NEW(), $ ;Selection line

      size: [0., 0.], $         ;Widget draw size
      map_size: [0., 0.], $     ;Image size
      
      ;;Line selection
      line_sel: [[0.,0.], [0.,0.]], $ ;Initial/final poinst of the
                                ;selected line with coordenates respect
                                ;widget_draw size.
      line_map_sel: [[0.,0.], [0.,0.]], $ ;Initial/final points of the
                                ;selected line with coordenates respect
                                ;image size.
      ;;Square selection
      square_sel: [[0.,0.], [0.,0.], $ ;Initial/final poinst of the
                   [0.,0.], [0.,0.]], $ ;selected square with
                                ;coordenates respect
                                ;widget_draw size.
      square_map_sel: [[0.,0.], [0.,0.], $ ;Initial/final points of the
                       [0.,0.], [0.,0.]], $ ;selected square with
                                ;coordenates respect
                                ;image size.

      selectionType: '', $      ;Specifies the selection type: LINE/SQUARE
      bSelecting: 0B, $         ;Are we making a selection?
      bHideSelection: 0B, $     ;Is visible the selection line?
      bDynamicSelection: 0B $   ;Emit SELECTION signals when we are
                                ;making the selection?
      }
END


NAME: SelectMap::Init
DESCRIPTION:
       Creates an instance of 'SelectMap' class.
PARAMETERS:
       parent - Parents widget ID.
EXTRA PARAMETERS:
       extra - Extra KEYWORD with options to be passed to the
               widget_draw.
+Code:
FUNCTION SelectMap::Init, parent, _EXTRA=extra

    ;;Initilize superclass
    result = self->EventAction::Init()

    IF NOT KEYWORD_SET(parent) THEN RETURN, 0

    ;;Create widget and object hieriarchy.
    wBase = WIDGET_BASE(parent)
    wDraw = WIDGET_DRAW(wBase, GRAPHICS_LEVEL=2, /EXPOSE_EVENTS, $
                        /BUTTON_EVENTS, /MOTION_EVENTS, _EXTRA=extra, $
                        UVALUE={class_name: 'SelectMap', object: self, $
                                handler: 'EventHandler'})
    
    self.parent_id = parent
    self.base_id = wBase
    self.widget_id = wDraw

    ;;Register the 'event' of the class
    self->AddEvent, 'SELECTION'
    self->AddEvent, 'MOTION'
    
    self->Initialize
    
    RETURN, 1
END


NAME: SelectMap::Initialize
DESCRIPTION:
       Initialize the state of the object. If it is executed when the
       object is running the object's state goes back to the same as
       the creation state. All possible used memory are free.
+Code:
PRO SelectMap::Initialize

    ;;Free memory usage
    self->Clear

    ;;Realize the WIDGET_BASE and get the IDLgrWindow object from,
    ;;WIDGET_DRAW
    WIDGET_CONTROL, self.base_id , /REALIZE
    WIDGET_CONTROL, self.widget_id, GET_VALUE=oWindow
    oWindow->SetProperty, QUALITY=0
    
    oView = OBJ_NEW('IDLgrView', ZCLIP=[0.2,-0.2], $
      VIEWPLANE_RECT=[0,0,1,1], COLOR=[50,50,70])
    oModel = OBJ_NEW('IDLgrModel')
    oLight = OBJ_NEW('IDLgrLight', TYPE=1, LOCATION=[0,0,12], $
      INTENSITY=0.95)

    ;;Initialize attributes
    geom = WIDGET_INFO(self.widget_id, /GEOMETRY)
    self.size = [geom.xsize, geom.ysize]
    self.map_size = [0., 0.]
    self.line_sel = [[0.,0.], [0.,0.]]
    self.line_map_sel = [[0.,0.], [0.,0.]]
    self.selectionType = 'SQUARE'
    self.bHideSelection = 0 ;Hide selection
    self.bDynamicSelection = 0  ;No dynamic selection
    self.bSelecting = 0

    ;;Save references to the objects
    oView->Add, oModel
    oModel->Add, oLight

    self.oWindow = oWindow
    self.oView = oView
    self.oModel = oModel
    
END


NAME: SelectMap::Cleanup
DESCRIPTION:
    Free memory used by the object.
+Code:
PRO SelectMap::Cleanup

    OBJ_DESTROY, [self.oWindow]
    
    self->Clear

    self->EventAction::Cleanup
END


NAME: SelectMap::Clear
DESCRIPTION:
       Free memory used by the object.
+Code:
PRO SelectMap::Clear
    ;;When destroy de IDLgrView the IDLgrModel are destroyed with all
    ;;its contents, included the image and seleccion line.
    OBJ_DESTROY, [self.oView, self.oPalette, self.oSelectLine]
END


NAME: SelectMap::SetPalette
DESCRIPTION:
       Sets a color palette used to show bachground image. Only takes
       efect if the background image is a X,Y array.
PARAMETERS:
    colors - 256x3 array values (RGB).
+Code:
PRO SelectMap::SetPalette, colors
    
    ;;Destroy the last palette (if exists)
    OBJ_DESTROY, self.oPalette
    
    oPalette = OBJ_NEW('IDLgrPalette', colors[*,0], colors[*,1], colors[*,2])
    
    ;;Save reference to the palette.
    self.oPalette = oPalette
END


NAME: SelectMap::SetMap
DESCRIPTION:
     Sets a background image. The image can be a (x,y) array that
     will be colored with the specified palette or may be a
     (3,x,y), (x,3,y) or (x,y,3) array (like an 'jpeg' image).
PARAMETERS:
     data_map - Array 2D or 3D with the image to show.
+Code:
PRO SelectMap::SetMap, data_map
    
    ;;Destroy previeus objects.
    OBJ_DESTROY, [self.oImage, self.oSelectLine]
    
    ;;Get dimension of the image and calcula the normalization factors
    ;;depending on the type of the image.
    sizes = SIZE(data_map, /DIMENSIONS)

    IF N_ELEMENTS(sizes) EQ 3 THEN BEGIN
        ;;Image 3,X,Y
        IF sizes[0] LE 4 THEN BEGIN
            xsize = sizes[1]
            ysize = sizes[2]
            xconv = NORMALIZE([0, xsize-1], Position=[0,1])
            yconv = NORMALIZE([0, ysize-1], Position=[0,1])
        ENDIF
        ;;Image X,3,Y
        IF sizes[1] LE 4 THEN BEGIN
            xsize = sizes[0]
            ysize = sizes[2]
            xconv = NORMALIZE([0, xsize-1], Position=[0,1])
            yconv = NORMALIZE([0, ysize-1], Position=[0,1])
        ENDIF
        ;;Image X,Y,3 
        IF sizes[2] LE 4 THEN BEGIN
            xsize = sizes[0]
            ysize = sizes[1]
            xconv = NORMALIZE([0, xsize-1], Position=[0,1])
            yconv = NORMALIZE([0, ysize-1], Position=[0,1])
        ENDIF
    ENDIF ELSE BEGIN
        ;;Image X,Y
        xsize = sizes[0]
        ysize = sizes[1]
        xconv = NORMALIZE([0, xsize-1], Position=[0,1])
        yconv = NORMALIZE([0, ysize-1], Position=[0,1])
    ENDELSE

    ;;Save the dimensions of the image.
    self.map_size = [xsize, ysize]

    ;;Create the image as a texture of polygon.
    oImage = OBJ_NEW('IDLgrImage', data_map, PALETTE=self.oPalette, $
      XCOORD_CONV=xconv, YCOORD_CONV=yconv)

    ;;Create the selection line object
    IF self.selectionType EQ 'LINE' THEN BEGIN
        connect_line = [2, 0, 1]
        oSelectLine = OBJ_NEW('IDLgrPolyline', self.line_map_sel, $
                              POLYLINES=connect_line, $
                              COLOR=[150,150,150], THICK=2, $
                              HIDE=self.bHideSelection, $
                              XCOORD_CONV=xconv, YCOORD_CONV=yconv)        
    ENDIF ELSE BEGIN
        connect_line = [4, 0, 1, 2, 3]
        oSelectLine = OBJ_NEW('IDLgrPolyline', self.square_map_sel, $
                              POLYLINES=connect_line, $
                              COLOR=[150,150,150], THICK=2, $
                              HIDE=self.bHideSelection, $
                              XCOORD_CONV=xconv, YCOORD_CONV=yconv)        
    ENDELSE 

    ;;Save object references
    self.oModel->Add, oImage
    self.oModel->Add, oSelectLine
    self.oImage = oImage
    self.oSelectLine = oSelectLine

END


NAME: SelectMap::Draw
DESCRIPTION:
         Draws the object.
+Code:
PRO SelectMap::Draw
    self.oWindow->Draw, self.oView
END


NAME: SelectMap::GetProperty
DESCRIPTION:
    Get the the properties of the object.
KEYWORD PARAMETERS:
      id - ID of the WIDGET_BASE over the object are created.
+Code:
 PRO SelectMap::GetProperty, ID=id

     id = self.base_id
 END


NAME: SelectMap::SetProperty
DESCRIPTION:
    Sets the properties of the object.
KEYWORD PARAMETERS:
       hide_selection - Show/hide the selection line.
       dynamic_selection - If true, SELECTION events are emited while a
                           selecction is doing.
+Code:
PRO SelectMap::SetProperty, $
  SELECTION_TYPE=selection_type, $
  DYNAMIC_SELECTION=dynamic_selection, $
  HIDE_SELECTION=hide_selection
        
    IF selection_type EQ 'LINE' OR selection_type EQ 'SQUARE' THEN BEGIN
        self.selectionType = selection_type
    ENDIF

    IF N_ELEMENTS(dynamic_selection) THEN BEGIN
        self.bDynamicSelection = dynamic_selection
    ENDIF

    IF N_ELEMENTS(hide_selection) THEN BEGIN
        self.bHideSelection = hide_selection
        self.oSelectLine->SetProperty, HIDE=hide_selection
    ENDIF
    
 END


NAME: SelectMap_EventHandler
DESCRIPTION:
       Object's event handler.
+Code:
PRO SelectMap::EventHandler, event

    ;;Expose Event
    IF event.type EQ 4 THEN BEGIN
        self->Draw
    ENDIF
    
    ;;Mouse down button
    IF (event.type EQ 0) AND (event.press EQ 1) THEN BEGIN
        IF NOT self.bHideSelection THEN BEGIN
            ;;Set that a selection is doing
            self.bSelecting = 1

            ;;Update the line coordenates
            self->UpdateLineSelection, event, /ALL
            self->UpdateSquareSelection, event, /ALL
            IF self.selectionType EQ 'LINE' THEN BEGIN
                connect_line = [2, 0, 1]
                self.oSelectLine->SetProperty, DATA=self.line_map_sel, $
                  COLOR=[255,255,0], POLYLINE=connect_line
            ENDIF ELSE BEGIN
                connect_line = [4, 0, 1, 2, 3]
                self.oSelectLine->SetProperty, DATA=self.square_map_sel, $
                  COLOR=[255,255,0], POLYLINE=connect_line            
            ENDELSE 
        ENDIF     
           
    ENDIF
    
    ;;Mouse up button
    IF (event.type EQ 1)  AND (event.release EQ 1)THEN BEGIN

        ;;Set that the selection are finished
        self.bSelecting = 0

        ;;Update the line corrdenates.
        self->UpdateLineSelection, event
        self->UpdateSquareSelection, event
            IF self.selectionType EQ 'LINE' THEN BEGIN
                self.oSelectLine->SetProperty, DATA=self.line_map_sel, $
                  COLOR=[255,255,255]
            ENDIF ELSE BEGIN
                self.oSelectLine->SetProperty, DATA=self.square_map_sel, $
                  COLOR=[255,255,255]  
            ENDELSE 

        ;;Generate a 'SELECTION' event.
        self->Draw
        self->EmitEvent, 'SELECTION', $
          EVENT_STRUCT={line_sel: self.line_sel, $
                        line_map_sel: self.line_map_sel}
    ENDIF
    
    ;;Mouse move
    IF (event.type EQ 2)  THEN BEGIN
        ;;If a selection is doing actualize the coordenates.
        IF self.bSelecting THEN BEGIN          
            self->UpdateLineSelection, event           
            self->UpdateSquareSelection, event
            IF self.selectionType EQ 'LINE' THEN BEGIN
                self.oSelectLine->SetProperty, DATA=self.line_map_sel
            ENDIF ELSE BEGIN
                self.oSelectLine->SetProperty, DATA=self.square_map_sel    
            ENDELSE 
            
            self->Draw
        ENDIF

        ;;Generate a 'MOTION' event.
        values = [event.x, event.y]
        convert = self->ConvertValuesW2M(values)
        self->EmitEvent, 'MOTION', $
          EVENT_STRUCT={ point_sel: values, $
                         point_map_sel: convert }
    ENDIF
    
END


NAME: SelectMap::UpdateLineSelection
DESCRIPTION:
       Get the actual coordenate points and convert respect the image
       size.
KEYWORD PARAMETERS:
       all - If set specify that the two points (origin, final) of
             the selection line must to be initialize. If not set,
             only the final point is converted.
NOTE: The 0 and 2 points of the square are the initial and final
       points respectively.
+Code:
PRO SelectMap::UpdateLineSelection, event, ALL=all

    xpoint = (event.x > 0) < (self.size[0]-1)
    ypoint = (event.y > 0) < (self.size[1]-1)
    
    IF KEYWORD_SET(all) THEN BEGIN
        self.line_sel[*,0] = [xpoint, ypoint]    
        self.line_map_sel[*,0] = self->ConvertValuesW2M(self.line_sel[*,0])
    ENDIF

    self.line_sel[*,1] = [xpoint, ypoint]
    self.line_map_sel[*,1] = self->ConvertValuesW2M(self.line_sel[*,1])
END


NAME: SelectMap::UpdateSquareSelection
DESCRIPTION:
       Get the actual coordenate points and convert respect the image
       size.
KEYWORD PARAMETERS:
       all - If set specify that the two points (origin, final) of
             the selection line must to be initialize. If not set,
             only the final point is converted.
NOTE: The 0 and 2 points of the square are the initial and final
       points respectively.
+Code:
PRO SelectMap::UpdateSquareSelection, event, ALL=all

    xpoint = (event.x > 0) < (self.size[0]-1)
    ypoint = (event.y > 0) < (self.size[1]-1)
    
    IF KEYWORD_SET(all) THEN BEGIN
        ;;Initial point
        self.square_sel[*,0] = [xpoint, ypoint]
        self.square_map_sel[*,0] = self->ConvertValuesW2M([xpoint, ypoint])
    ENDIF

    ;;Final point
    self.square_sel[*,2] = [xpoint, ypoint]
    self.square_map_sel[*,2] = self->ConvertValuesW2M([xpoint, ypoint])

    ;;Other points
    xinit = self.square_sel[0,0]
    yinit = self.square_sel[1,0]
    width = xinit - xpoint
    height = yinit - ypoint

    self.square_sel[*,1] = [(xinit + width), ypoint]
    self.square_map_sel[*,1] = self->ConvertValuesW2M([xpoint, ypoint])
    
    self.square_sel[*,3] = [xpoint, (ypoint + height)]
    self.square_map_sel[*,3] = self->ConvertValuesW2M([xpoint, ypoint])


END


NAME: SelectMap::ConvertValuesW2M
DESCRIPTION:
       Convert a pair of values from widget size relative coordenatos
       to the image relativa size coordenates.
+Code:
FUNCTION SelectMap::ConvertValuesW2M, values

    values[0] = (values[0] > 0) < (self.size[0]-1)
    values[1] = (values[1] > 0) < (self.size[1]-1)

    convert = values
    convert[0] = values[0] * (self.map_size[0]-1) / (self.size[0]-1)
    convert[1] = values[1] * (self.map_size[1]-1) / (self.size[1]-1)
    
    RETURN, convert
END



· Created by the PerlScript documentation generator for IDL ·
· Thu Dec 2 16:01:50 2004 ·