In iTools Synchronizing Annotation Layer Movement With Visualization Layer Movement
Home
Register, Login   

     Tech Tips
 

Printable Version
Article Title: In iTools Synchronizing Annotation Layer Movement With Visualization Layer Movement
Article ID: 3812
Last Updated: 12/7/2009 12:03:03 PM
Products: IDL
Product Version: IDL - 6.1

Topic:

 

If you open the 'Visualization Browser' of any simple iTool, you will notice that there is under each Window->View hierarchy a "Visualization Layer" branch and an "Annotation Layer" branch. The "Visualization Layer" is designed to contain the main data and plot/image objects of the iTools visualization. The "Annotation Layer" is designed to contain all the graphics objects in your visualization that are designed to annotate. In IDL through version 6.1 changes in the position or aspect of a visualization layer plot or image do not automatically cascade to the objects in the annotation layer that might be annotating that plot or image. Realizing that some iTools programmers might need a way to link some movements in the one layer with matching movements in the other, this Tech Tip is designed to illustrate three things:

  1. How to programatically custom position annotations in your iTool Visualization window so that they register nicely with objects in the "plot dataspace."
  2. How to subsequently get these annotations to move in tandem with the movement of the plot dataspace.
  3. Finally, to illustrate many IDL command line tricks that will help new iTools developers uncover methods and properties in the rapidly evolving iTools API, which may not yet be documented.

These teachings are conveyed through the example of "attaching" a vertical Colorbar to an iContour.

We should add a very loud warning here that: Methods and Properties that are not currently documented in the 'IDL Reference Guide', the 'iTool Developer's Guide' or the 'iTool User's Guide' are subject to change. The source code you write with such undocumented elements may not work on future versions of IDL. Some of these methods and properties are indispensable - i.e. there is no good way to work without them - so it is understandable that programmers will want to implement them immediately. We simply recommend that, wherever there is a documented solution, use that rather than any easier undocumented substitute.


Discussion:

There is not yet functionality precompiled into iTools that will automatically synchronize the movement of objects within the Annotation Layer to movements occurring in the Visualization Layer. For example, the arrow you point at a plot line will not move automatically when the user drags the plot to a new window location. The axes will - they are part of the same "Visualization Layer" - it is just the annotation objects that won't. Until such functionality is added, the methodology described in the example code of this Tech Tip might help you find object properties and routines that can get your iTool application to programatically coordinate the layout and movements in these two layers.

The example code is not a compilable procedure, rather it is a batch listing of commands that iTools programmers can run from the IDLDE command line. And this example is not designed to show what exact routines to add to any iTools subclasses you are creating, but you can probably extrapolate the routines from the code shown below. For programmers fairly new to iTools, the copious comments give a fairly thorough introduction to how one might study/debug a given iTool visualization. For more experienced iTools programmers looking simply for the annotation/visualization layer synchronization algorithms, you will find most of what you need starting with the section "POSITIONING THE ANNOTATION WITH RESPECT TO THE PLOT" halfway through the example. For Computer Graphics experts, you can probably skip a lot of the layman's explanations of Computer Graphics principles that appear in the comments.

The below example can be downloaded at the following link icontour_vert_colorbar.pro

Example Code:

; LOAD A SIMPLE ICONTOUR
; Make a color table to pass to the ICONTOUR procedure
loadct, 5
tvlct, r, g, b, /get
rgb_table = bytarr(3,256)
rgb_table[0,*] = r
rgb_table[1,*] = g
rgb_table[2,*] = b
; Make the contour data
dummy_data = dist(360)
iContour, dummy_data, NAME='DIST Contour', RGB_TABLE=rgb_table, $
    IDENTIFIER=idTool

; GET A REFERENCE TO THE CURRENT TOOL.
; This provides our main key to other object references and ID's in the
; visualization hierarchy.
void = itgetcurrent(TOOL=oTool)

; PRACTICE TRIGGERING AN OPERATION - INSERTING THE COLORBAR PROGRAMATICALLY
; For this we need the ID of the operation that does the menubar's
; 'Insert->Colorbar' action.
; Let's assume you are relatively new to iTool addressing syntax. To get a
; handle on that operation you have to figure that the iTool ID will contain
; the word "COLORBAR". Thus ...
temp = oTool->FindIdentifiers('*COLORBAR*')
help, temp
;TEMP            STRING    = Array[2]
print, temp, format='(a)'
;/TOOLS/CONTOUR TOOL/OPERATIONS/INSERT/COLORBAR
;/TOOLS/CONTOUR TOOL/CURRENT STYLE/VISUALIZATIONS/COLORBAR
; It is intuitive that the ID with the string "INSERT" is the one that we are
; looking for.
idOpInsertColorbar = oTool->FindIdentifiers('*INSERT/COLORBAR')
print, idOpInsertColorbar
;/TOOLS/CONTOUR TOOL/OPERATIONS/INSERT/COLORBAR

; We made the above queries, so that we can run this iTool method, which
; does programatically what the GUI menu selection would do.
print, oTool->DoAction(idOpInsertColorbar)
; Check the iTool GUI and observe the colorbar and its horizontal orientation.        1

; RESEARCH PROPERTIES AND METHODS OF THE COLORBAR
; My goal is to figure out how to turn the colorbar upright.
; For this I might want both its ID and its object reference.
; You have to figure the new colorbar object's ID has to have the word
; "COLORBAR" in it.
temp = oTool->FindIdentifiers('*COLORBAR*')
help, temp
;TEMP            STRING    = Array[3]
print, temp, format='(a)'
;/TOOLS/CONTOUR TOOL/OPERATIONS/INSERT/COLORBAR
;/TOOLS/CONTOUR TOOL/CURRENT STYLE/VISUALIZATIONS/COLORBAR
;/TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/ANNOTATION LAYER/COLORBAR
; It is pretty clear that the ID with "ANNOTATION LAYER" is what I am
; looking for.
idColorbar = oTool->FindIdentifiers('*ANNOTATION LAYER/COLORBAR')
print, idColorbar
;/TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/ANNOTATION LAYER/COLORBAR
; This it the main iTool routine for retrieving the object reference
; that corresponds to an ID.
oColorbar = oTool->GetByIdentifier(idColorbar)
; HELP, /OBJECTS is a nice quick reference tool that shows a lot more options
; than what you might find in the early generation iTool documentation. It
; provides quick reference to a lot of the methods and perhaps ALL of the
; superclasses that your object can call. It shows many, but not all, of the
; methods that it has inherited. Consequently, you sometimes have to check the
; direct documentation of the superclasses (or run "HELP, /OBJECTS" on an
; object of that type) to find what might be most useful to you.
help, oColorbar, /objects
;** Object class IDLITVISCOLORBAR, 1 direct superclass, 66 known methods
;   Superclasses:
;      IDLITVISUALIZATION  
;      _IDLITVISUALIZATION
;      _IDLITCONTAINER
;      _IDLITPROPERTYAGGREGATE
;      IDLGRMODEL
;      IDLGRCONTAINER
;      IDL_CONTAINER
;      IDLGRCOMPONENT
;      IDLITCOMPONENT
;      IDLITSELECTPARENT
;      IDLITIMESSAGING
;      IDLITPARAMETER
;   Known Function Methods:
;      _IDLITVISUALIZATION::CREATE
;      _IDLITCONTAINER::GET
;      _IDLITPROPERTYAGGREGATE::GETAGGREGATE
;      _IDLITVISUALIZATION::GETCENTERROTATION
;      _IDLITVISUALIZATION::GETDATASPACE
;      _IDLITVISUALIZATION::GETDEFAULTSELECTIONVISUAL
;      IDLITCOMPONENT::GETFULLIDENTIFIER
;      _IDLITVISUALIZATION::GETMANIPULATORTARGET
;      IDLITPARAMETER::GETPARAMETER
;      IDLITCOMPONENT::GETPROPERTYBYIDENTIFIER
;      _IDLITVISUALIZATION::GETREQUESTEDAXESSTYLE
;      _IDLITVISUALIZATION::GETSELECTIONVISUAL
;      IDLITIMESSAGING::GETTOOL
;      IDLITVISUALIZATION::GETTYPES
;      _IDLITVISUALIZATION::GETXYZRANGE
;      IDLITVISCOLORBAR::INIT
;      _IDLITVISUALIZATION::IS3D
;      _IDLITPROPERTYAGGREGATE::ISAGGREGATEINTERSECTION
;      _IDLITVISUALIZATION::ISISOTROPIC
;      _IDLITVISUALIZATION::ISMANIPULATORTARGET
;      _IDLITVISUALIZATION::ISSELECTED
;      _IDLITVISUALIZATION::MATCHESTYPES
;      IDLITPARAMETER::QUERYPARAMETER
;      IDLITPARAMETER::QUERYPARAMETERDESCRIPTOR
;      IDLITCOMPONENT::QUERYPROPERTY
;      _IDLITVISUALIZATION::REQUESTSAXES
;      _IDLITVISUALIZATION::SEEKPIXELATEDVISUALIZATION
;      IDLITVISUALIZATION::SETPARAMETERSET
;      _IDLITVISUALIZATION::_GETLAYER
;      _IDLITVISUALIZATION::_GETWINDOWANDVIEWG
;      _IDLITPROPERTYAGGREGATE::_GETALLPROPERTYDESCRIPTORS
;   Known Procedure Methods:
;      _IDLITVISUALIZATION::ADD
;      _IDLITPROPERTYAGGREGATE::ADDAGGREGATE
;      _IDLITVISUALIZATION::AGGREGATE
;      IDLITIMESSAGING::DOONNOTIFY
;      IDLGRMODEL::DRAW
;      IDLGRMODEL::DRAWSELF
;      _IDLITPROPERTYAGGREGATE::GETAGGREGATEPROPERTY
;      IDLITPARAMETER::GETPARAMETERATTRIBUTE
;      IDLITVISCOLORBAR::GETPROPERTY
;      IDLITCOMPONENT::GETPROPERTYATTRIBUTE
;      IDLITVISCOLORBAR::GETPROPERTY
;      IDLITVISUALIZATION::ONDATACHANGE
;      IDLITVISCOLORBAR::ONDATACHANGEUPDATE
;      IDLITVISUALIZATION::ONDATACOMPLETE
;      IDLITVISUALIZATION::ONDATADELETE
;      _IDLITVISUALIZATION::ONWORLDDIMENSIONCHANGE
;      IDLITPARAMETER::REGISTERPARAMETER
;      IDLITCOMPONENT::REGISTERPROPERTY
;      IDLGRMODEL::RESET
;      _IDLITVISUALIZATION::SELECT
;      _IDLITPROPERTYAGGREGATE::SETAGGREGATEPROPERTY
;      _IDLITVISUALIZATION::SETCURRENTSELECTIONVISUAL
;      IDLITPARAMETER::SETPARAMETER
;      IDLITPARAMETER::SETPARAMETERATTRIBUTE
;      IDLITVISCOLORBAR::SETPROPERTY
;      IDLITCOMPONENT::SETPROPERTYBYIDENTIFIER
;      IDLITVISCOLORBAR::SETPROPERTY
;      IDLGRMODEL::TRANSLATE
;      _IDLITVISUALIZATION::UPDATESCENE
;      _IDLITVISUALIZATION::UPDATESELECTIONVISUAL
;      _IDLITVISUALIZATION::UPDATESELECTIONVISUALVISIBILITY
;      _IDLITVISUALIZATION::_ACCUMULATEXYZRANGE
;      _IDLITVISUALIZATION::_CHECKDIMENSIONCHANGE
;      IDLITVISCOLORBAR::_REGISTERPROPERTIES
;      IDLITIMESSAGING::_SETTOOL
; Now that I know that a colorbar annotation is an 'IDLitVisColorbar' object
; I can look at IDL's Online Help.
?IDLitVisColorbar
; Notice how little information is yet documented there. So my next iTool
; research utility is the QUERYPROPERTY method that every iTool component
; has implemented. (I show this here for thoroughness. Further below I 
; demonstrate ITPROPERTYREPORT, currently in everybody's IDL 'examples'
; directory and documented in the Developer's Guide. That provides some
; shortcuts compared to the below.)
propsColorbar = oColorbar->QueryProperty()
print, propsColorbar, format='(a)'
;NAME
;DESCRIPTION
;HIDE
;CLIP_PLANES
;DEPTH_TEST_DISABLE
;DEPTH_TEST_FUNCTION
;DEPTH_WRITE_DISABLE
;LIGHTING
;SELECT_TARGET
;TRANSFORM
;BORDER_ON
;ORIENTATION
;LOCATION
;DATA_POSITION
;TRANSPARENCY
;ALPHA_CHANNEL
;COLOR
;PALETTE
;DIRECTION
;GRIDSTYLE
;THICK
;MAJOR
;MINOR
;TICKLEN
;SUBTICKLEN
;TICKINTERVAL
;TICKLAYOUT
;TICKDIR
;LOG
;EXACT
;EXTEND
;NOTEXT
;TEXTPOS
;TICKFORMAT
;TICKUNITS
;TICK_DEFINEDFORMAT
;AXIS_TITLE
;TEXT_COLOR
;NORM_LOCATION
;RANGE
;CRANGE
;TICKFRMTDATA
;FONT_INDEX
;FONT_STYLE
;FONT_SIZE
; An "ORIENTATION" property AND a "DIRECTION" property; that's confusing!
; Maybe the source code can quickly reveal what I want. I know my object
; type is named "IDLitVisColorbar". Therefore, it is most likely defined
; in its own 'idlitviscolorbar__define.pro' file. This is where the IDL
; command line command .EDIT comes in handy. When the file opens in the
; editor, I search straight for the string "::SetProperty". That is where
; all of the component '__define.pro' files list (in the procedure comments)
; their settable properties.
.edit IDLitVisColorbar__define
; In this case the source code is not so straightforward, so I quickly
; see if the iContour GUI can help. Sure enough, there is an ORIENTATION
; property, but no DIRECTION. ORIENTATION is defined as "Horizontal". Is
; that 2-option property really stored as a string?
oColorbar->GetProperty, ORIENTATION=temp
print, temp
;           0
; It's an int; so I now check to see if this is an "enumerated list" as
; one might expect from a dropdown list on an iTools property sheet.
; 'GetPropertyAttribute' is available to all iTool components through 
; the 'IDLitComponent' superclass.
oColorbar->GetPropertyAttribute, 'ORIENTATION', TYPE=orientationDatatype
print, orientationDatatype
;           9
; A link from Online Help for IDLitComponent::GetPropertyAttribute
; confirms that 9 = "enumerated list" and reveals this additional keyword
; option.
oColorbar->GetPropertyAttribute, 'ORIENTATION', $
    ENUMLIST=orientationOptions
print, orientationOptions
;Horizontal Vertical
; Looks like I can be confident that "Vertical" orientation maps to the
; value of 1.

; PRACTICE MODIFYING VISUALIZATION PROPERTIES -
; STANDING THE COLORBAR VERTICAL AND CHANGING ITS TEXT PROPERTIES
; We made the above queries, so that we can run this iTool method, which
; does programatically what modifying a property on the Visualization
; Browser does.
print, oTool->DoSetProperty(idColorbar, 'ORIENTATION', 1)
;           1
oTool->CommitActions
; One consequence of calling DOSETPROPERTY is that your action is recorded
; in iTools' 'UNDO/REDO' buffer. When you are developing an application,
; you may prefer that such recording NOT occur, in which case the following
; call would substiture for the above two:
;oColorbar->SetProperty, ORIENTATION=1
; I want to clean up the appearance of the text on the colorbar. I found
; the property names I needed in the QUERYPROPERTY() list above.
oColorbar->GetProperty, TEXTPOS=temp
print, temp
;           0
print, oTool->DoSetProperty(idColorbar, 'TEXTPOS', 1)
;           1
oTool->CommitActions
oColorbar->GetProperty, FONT_SIZE=temp
print, temp
;      12
print, oTool->DoSetProperty(idColorbar, 'FONT_SIZE', 8)
;           1
oTool->CommitActions

; POSITIONING THE ANNOTATION WITH RESPECT TO THE PLOT
; The remaining steps in this procedure are not so intuitive as the above.
; A deeper understanding of the original IDL Object Graphics classes, from
; which iTools inherits, is useful here.
; The critical objects needed to finish this job are 1) the Contour object
; (IDLitVisContour) and 2) the Visualization Layer object (IDLitGrLayer).
; From the Contour object we just need its "graphics transform matrix".
; From the Layer we need the definitions of the coordinate system for our
; Contour. Those definitions provide the key to how to use the data in the
; Contour's transform matrix.
; I start with the information from Contour's visualization layer:
temp = oTool->FindIdentifiers('*VISUALIZATION LAYER')
help, temp
;TEMP            STRING    = Array[2]
print, temp, format='(a)'
;/TOOLS/CONTOUR TOOL/CURRENT STYLE/VISUALIZATIONS/VISUALIZATION LAYER
;/TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/VISUALIZATION LAYER
idVisLayer = oTool->FindIdentifiers('*VIEW_1/VISUALIZATION LAYER')
print, idVisLayer
;/TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/VISUALIZATION LAYER
oVisLayer = oTool->GetByIdentifier(idVisLayer)
; I use the next 2 calls to look for methods and/or properties that will
; show the coordinate system of the layer as a whole, and that will show
; what margins there are between the outside bounds of the Contour and
; the outside edges of the Layer. The Contour's bounds are identifiable
; by the axes box. The Layer's bounds are, at least when iContour first
; loads, identifiable by the outer edges of the view window. Both objects
; are working with normalized coordinates with their center in the center
; of the view window (at least when iContour first loads). You will find
; that they share the same coordinate system, which means that one or the
; other, perhaps both, do NOT have a simple -1.0 - +1.0 range. The below
; steps unravel the mysteries of the coordinate system we need to address.
help, oVisLayer, /objects
;** Object class IDLITGRLAYER, 4 direct superclasses, 35 known methods
;   Superclasses:
;      _IDLITCONTAINER  
;      IDLGRVIEW  
;      IDLGRCONTAINER
;      IDL_CONTAINER
;      IDLGRCOMPONENT
;      IDLITCOMPONENT
;      IDLITSELECTPARENT  
;      IDLITIMESSAGING  
;   Known Function Methods:
;      IDLITGRLAYER::COMPUTEVIRTUALFRUSTUMRECT
;      IDLITGRLAYER::CREATE
;      IDLITGRLAYER::GET
;      _IDLITCONTAINER::GETBYIDENTIFIER
;      IDLITGRLAYER::GETCURRENTDATASPACE
;      IDLITCOMPONENT::GETFULLIDENTIFIER
;      IDLITCOMPONENT::GETPROPERTYBYIDENTIFIER
;      IDLITIMESSAGING::GETTOOL
;      IDLITGRLAYER::GETWORLD
;      IDLITGRLAYER::INIT
;      IDLITCOMPONENT::QUERYPROPERTY
;      IDLITCOMPONENT::_GETALLPROPERTYDESCRIPTORS
;      IDLITGRLAYER::_ROUNDMARGIN
;   Known Procedure Methods:
;      IDLITGRLAYER::ADD
;      IDLITGRLAYER::CROPFRUSTUM
;      IDLITIMESSAGING::DOONNOTIFY
;      IDLGRVIEW::DRAW
;      IDLITGRLAYER::GETPROPERTY
;      IDLITCOMPONENT::GETPROPERTYATTRIBUTE
;      IDLITGRLAYER::GETPROPERTY
;      IDLITGRLAYER::ONDATACHANGE
;      IDLITGRLAYER::ONDATACOMPLETE
;      IDLITGRLAYER::ONVIEWPORTCHANGE
;      IDLITCOMPONENT::REGISTERPROPERTY
;      IDLITGRLAYER::SETCURRENTDATASPACE
;      IDLITSELECTPARENT::SETPRIMARYSELECTEDITEM
;      IDLITGRLAYER::SETPROPERTY
;      IDLITCOMPONENT::SETPROPERTYATTRIBUTE
;      IDLITCOMPONENT::SETPROPERTYBYIDENTIFIER
;      IDLITGRLAYER::SETSELECTEDITEM
;      IDLITGRLAYER::SETPROPERTY
;      IDLITGRLAYER::_CORRECTFORASPECTRATIO
;      IDLITGRLAYER::_CORRECTFORZOOM
;      IDLITGRLAYER::_REGISTERPROPERTIES
;      IDLITGRLAYER::_UPDATEMARGINS
; I don't see anything above that will return to me simple coordinate
; information, so I check the properties. This time I will use the
; thorough ITPROPERTYREPORT utility, introduced in 6.1, and documented
; on page 387 of the 6.1 'itooldevguide.pdf'. 
itpropertyreport, oTool, idVisLayer
;% Compiled module: ITPROPERTYREPORT.
;
;Properties of /TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/VISUALIZATION LAYER
;
;Identifier               Name                Type        
;----------               ----                ----        
;NAME                     Name                STRING      
;DESCRIPTION              Description         STRING      
;HIDE                     Show                ENUMLIST    
;COLOR                    Background color    COLOR       
;DEPTH_CUE                Depth cue           USERDEF     
;DIMENSIONS               Viewport dimensions USERDEF     
;DOUBLE                   Double precision    BOOLEAN     
;EYE                      Eye distance        FLOAT       
;LOCATION                 Viewport location   USERDEF     
;PROJECTION               Projection          ENUMLIST    
;TRANSPARENT              Transparent         BOOLEAN     
;UNITS                    Units               ENUMLIST    
;VIEWPLANE_RECT           Viewplane rectangle USERDEF     
;ZCLIP                    Z clipping          USERDEF     
;_PROJECTION              Projection          ENUMLIST    
;STRETCH_TO_FIT           Stretch to fit      BOOLEAN     
;MARGIN_2D_X              X margin            FLOAT       
;MARGIN_2D_Y              Y margin            FLOAT       
;DEPTHCUE_BRIGHT          Depth cue bright    FLOAT       
;DEPTHCUE_DIM             Depth cue dim       FLOAT
; Ahhh, VIEWPLANE_RECT and MARGIN_... properties; that's what we need.
oVisLayer->GetProperty, VIEWPLANE_RECT=vrVisLayer
print, vrVisLayer
;      -1.3984375      -1.0000000       2.7968750       2.0000000
oVisLayer->GetProperty, MARGIN_2D_X=xMarginVisLayer
oVisLayer->GetProperty, MARGIN_2D_Y=yMarginVisLayer
print, xMarginVisLayer, yMarginVisLayer
;      0.24900000      0.15000000
; I better check that there isn't anything out of sync between the
; coordinate system of Contour's "Visualization Layer" and the coordinate
; system of Colorbar's "Annotation Layer".
idAnnoLayer = oTool->FindIdentifiers('*VIEW_1/ANNOTATION LAYER')
print, idAnnoLayer
;/TOOLS/CONTOUR TOOL/WINDOW/VIEW_1/ANNOTATION LAYER
oAnnoLayer = oTool->GetByIdentifier(idAnnoLayer)
oAnnoLayer->GetProperty, VIEWPLANE_RECT=vrAnnotationLayer
print, vrAnnotationLayer
;      -1.3984375      -1.0000000       2.7968750       2.0000000
; Good! The two layers have the same coordinate system.
; How should we interpret these numbers?
; The TRANSFORM property of the IDLitVisColorbar object will help to
; DEMONSTRATE the interpretation. We can, namely, move an annotation
; object to a specific location by manipulating the values in the
; rightmost column of the object's "graphics transform matrix".
oColorbar->GetProperty, TRANSFORM=t
print, t
;       1.0000000      0.00000000      0.00000000     -0.50000000
;      0.00000000       1.0000000      0.00000000     -0.75000000
;      0.00000000      0.00000000       1.0000000      0.00000000
;      0.00000000      0.00000000      0.00000000       1.0000000
; The value in index [3,0] is giving the current X location of the
; colorbar object. Index [3,1] is giving the Y location. (2D graphics
; do not generally use Z location, which is stored at index [3,2].)
; Thus, we can get a better view of the coordinate system of the
; viewplane rectangle, if we try:
new_colorbar_t = t
new_colorbar_t[3,0] = vrVisLayer[0]   ; -1.398
new_colorbar_t[3,1] = vrVisLayer[1]   ; -1.0
print, oTool->DoSetProperty(idColorbar, 'TRANSFORM', new_colorbar_t)
;           1
oTool->CommitActions
; Notice how this positions the colorbar flush with the lower-left corner
; of the visualization. Thus, indexes 0 and 1 of the viewplane rectangle
; hold the X/Y-coordinate of the lower-left hand corner of the view window.
; Indexes 2 and 3 of the viewplane rectangle show the full height and
; width of the initial view window in coordinate units.
; [Why is the VIEWPLANE_RECT so uneven? See footnote at bottom.*]

; How do we find the coords for the boundaries of the plot axis box?
; This is where the Layer's margin information is required
print, xMarginVisLayer, yMarginVisLayer
;      0.24900000      0.15000000
; The above numbers are in percent, and are actually a property that is
; user-modifiable in the Visualization browser. What it means is that the
; edges of the initial contour are recessed 25% in from the left and 25%
; in from the right side of the view window. Thus, if the view window is
; 2.7968750 units wide and the left edge of the window is at coordinate
; -1.3984375, the left edge of the graph (the left Y-axis) will be at
; X-coordinate -0.699219 (= -1.3984375 + (0.25 * 2.7968750)). The bottom
; of the graph, with a 'yMargin' of 15%  will be at
; -1.0 + (0.15 * 2.0) =  -0.7.
; Thus, the following should put our colorbar at the origin of the graph.
new_colorbar_t[3,0] = -0.699219
new_colorbar_t[3,1] = -0.7
print, oTool->DoSetProperty(idColorbar, 'TRANSFORM', new_colorbar_t)
;           1
oTool->CommitActions
; Look at the iContour now, and notice how this works on the X dimension,
; but it produces a strange result in the Y dimension. The explanation for
; this has to do with the "anisotropic scaling" of the default dataspace.
; You will see what is meant by this by, on the Visualization Browser,
; highlighting the 'Visualization Layer -> Data Space', and changing its
; property to 'Isotropic Scaling'. Now you see how the above command
; actually DID in a way find the origin of our plot axes. (If you do not
; understand 'Isotropic Scaling' see footnote 2 below.**)
; Unfortunately, the above algorithm is not complete enough for the
; anisotropic view that most visualizations work with. So, we find an
; alternative property of iTools, one necessary for later moving our
; colorbar, that is also helpful for its initial positioning.

; USING THE CONTOUR TRANSFORM MATRIX FOR POSITIONING
; The Cumulative Transform Matrix, a property of every 'IDLgrModel' and,
; by inheritance, a part of the IDLitVisContour object, provides us with
; the last key to the coordinate system that we are looking for.
idContour = oTool->FindIdentifiers('*CONTOUR*', /VISUALIZATIONS)
oContour = oTool->GetByIdentifier(idContour)
; We try to find out how to get the current cumulative transform matrix
; through the usual iTools queries discussed above.
itpropertyreport, oTool, idContour
help, oContour, /objects
; The output of these calls reveals two items of interest: 'oContour' has
; a TRANSFORM property and 'oContour' has an inherited method
; 'IDLgrModel::GetCTM'. 'oContour's TRANSFORM property returns a unit
; matrix on iTools initialization. This must be the transform matrix of
; just the contour object by itself, not of the whole layer model that is
; containing it. Since we want to coordinate the contour's "layer" with the
; annotation's "layer" we need the cumulative transform matrix, and this is
; where the IDLgrModel::GetCTM method looks promising:
ctmContour = oContour->GetCTM()
print, ctmContour
;    0.0038997214      0.00000000      0.00000000     -0.70000000
;      0.00000000    0.0027298050      0.00000000     -0.49000000
;      0.00000000      0.00000000       1.0000000      0.00000000
;      0.00000000      0.00000000      0.00000000       1.0000000
; The above transform matrix is the only one we need, but the below call
; helps to better understand the meaning of transform matrix data.
ctmColorbar = oColorbar->GetCTM()
print, ctmColorbar
;       1.0000000      0.00000000      0.00000000     -0.69921899
;      0.00000000       1.0000000      0.00000000     -0.69999999
;      0.00000000      0.00000000       1.0000000      0.00000000
;      0.00000000      0.00000000      0.00000000       1.0000000
; Notice how the CTM for the colorbar object is identical to the value
; of the last 'new_colorbar_t' that we set the colorbar's TRANSFORM
; property to. I wonder what will happen if we set the colorbar's
; TRANSFORM location indexes equal to the contour's CTM values.
new_colorbar_t[3,0] = ctmContour[3,0]   ; -0.70000000
new_colorbar_t[3,1] = ctmContour[3,1]   ; -0.49000000
print, oTool->DoSetProperty(idColorbar, 'TRANSFORM', new_colorbar_t)
;           1
oTool->CommitActions
; View the iContour now. This turns out to be a pretty simple key to
; finding the contour plot's origin. I discover, however, that for the
; right-side plot border I still need the VIEWPOINT_RECT and MARGIN_X_2D
; information. Thus:
rightEdgeCoord = vrVisLayer[0] + vrVisLayer[2] - $
    (xMarginVisLayer * vrVisLayer[2])
print, rightEdgeCoord
;      0.69921875
; ... then from the contour transform matrix:
bottomEdgeCoord = ctmContour[3,1]
new_colorbar_t[3,0] = rightEdgeCoord
new_colorbar_t[3,1] = bottomEdgeCoord
newCoords = [rightEdgeCoord, bottomEdgeCoord, 0]
print, oTool->DoSetProperty(idColorbar, 'TRANSFORM', new_colorbar_t)
;           1
oTool->CommitActions
; Voilą.

; USING THE CONTOUR TRANSFORM MATRIX FOR SYNCHRONIZING ANNOTATION/COLORBAR
; WITH CONTOUR MOVEMENT
; Simple dragging movement on a 2D plane is known in graphics parlance as
; "translation", and a possible method for performing such dragging pro-
; gramatically is currently only documented in the Online Help for the
; long-standing 'IDLgrModel' class.
; The values to feed to IDLgrModel::Translate turn out to be pretty simple.
; Notice the following test. First, I reprint the matrix from above:
ctmContourOld = ctmContour
print, ctmContourOld
;    0.0038997214      0.00000000      0.00000000     -0.70000000
;      0.00000000    0.0027298050      0.00000000     -0.49000000
;      0.00000000      0.00000000       1.0000000      0.00000000
;      0.00000000      0.00000000      0.00000000       1.0000000
; Then, I go to the iContour and drag the contour plot with my mouse.
; Let's look at what this drag did to the contour's CTM:
ctmContourNew = oContour->GetCTM()
print, ctmContourNew
;    0.0038997214      0.00000000      0.00000000      -1.0593750
;      0.00000000    0.0027298050      0.00000000     -0.82854167
;      0.00000000      0.00000000       1.0000000      0.00000000
;      0.00000000      0.00000000      0.00000000       1.0000000
; Everything is the same except the right-column numbers. And it is now
; not hard for me to see that those numbers correspond to the location
; of the origin of the contour plot with respect to the origin (center)
; of our view rectangle. The movement I just performed then, could be
; defined as follows:
dx = ctmContourNew[3,0] - ctmContourOld[3,0]
dy = ctmContourNew[3,1] - ctmContourOld[3,1]
; If this were a 3D plot with a Z direction, then I could also
; calculate a 'dz' with element [3,2] of the transform matrices. But
; I now have all I need to programatically move the colorbar to
; its former position relative to the contour.
oColorbar->Translate, dx, dy, 0
; Now that is the best method to call, if you do not care that this
; translation was not recorded in this iContour's UNDO/REDO buffer.
; This DOES update the TRANSFORM property of the colorbar object, but
; if you need to have it recorded for possible later User Interface
; 'Undo' actions, then you need to perform the DoSetProperty method
; that was demo'ed above, e.g.:
;new_colorbar_t[3,0] += dx
;new_colorbar_t[3,1] += dy
;print, oTool->DoSetProperty(idColorbar, 'TRANSFORM', new_colorbar_t)

; One other 'translation' option I should mention: Some annotation
; objects, like IDLitVisText objects for example, can be
; programatically added to the Visualization Layer. If you take that
; approach, then an alternative algorithm for synchronizing that
; object's movement with your plot object would be to programatically
; "group" the objects with a call to the 'Edit->Grouping->Group'
; operation after you have run the 'Select' procedure method on the
; objects you want to group. The group will then "transform" together
; until they are "ungroup"ed. You just need to remember that up to
; at least IDL 6.1 objects in the Annotation Layer cannot be
; "group"ed with objects in the Visualization Layer this way.



; * FOOTNOTE ON VIEWPLANE_RECT DIMENSIONS:
; Our example showed a VIEWPLANE_RECT values of:
;      -1.3984375      -1.0000000       2.7968750       2.0000000
; The range of the width dimension (2.79 units wide) is explained by the
; uneven dimensions of the view window. By default, the initial iContour
; window starts at 537 x 384 pixels. iTools work with normalized
; coordinates. The design decision was made that the smaller pixel
; dimension, in this case the height, should be normalized to a range of
; -1.0 to +1.0. Hence, the other dimension, basing its measurements on
; the same pixel mapping, has a range extending beyond -1.0 to +1.0.
; The exact range is exactly -1.0*(537/384) to +1.0*(537/384), which
; equals -1.3984375 to +1.3984375.

; ** FOOTNOTE ON ISOTROPIC SCALING:
; To best understand 'Isotropic Scaling' run an exponential curve example
; like:
;    iPlot, findgen(10), findgen(10)^2
; Change the 'Data Space' 'Isotropic Scaling' property from "Automatic" to
; "Isotropic Scaling". The result you see demonstrates how isotropic
; scaling enforces that the pixel-width-to-data ratio is identical to
; the pixel-height-to-data ratio, not a very good graph view if the X and
; Y data ranges are vastly different. The goal of anisotropic scaling is
; to set pixel-width-to-data and pixel-height-to-data ratios based on the
; window view dimensions, so that the plot display looks nice within the
; current window borders.


 
 Quick Links

   Contact a Representative
   Request Literature
   Events
   User Community
   Subscribe
 
 Product Information

   IDL
   ENVI
   ENVI EX
   IAS
   NITF for ArcGIS
   Professional Services
   Events & Training

Home   |   Company   |   Products & Services   |   Academic   |   Events & Training   |   Downloads   |   User Community   |   Support |   Site Map

Privacy Statement ©2008 ITT Visual Information Solutions