; File: icontour_vert_colorbar.pro ; Syntax: @ICONTOUR_VERT_COLORBAR ; Purpose: This is an IDL "batch procedure", designed to demonstrate 3 tricks ; of iTool program development: ; 1) IDLDE Command Line tricks to find methods and properties of the current ; iTool visualization, including undocumented ones. The tricks are ; explained in detail in the comments of this batch procedure. ; 2) How to register the position of Annotation objects against the position ; of plot/data objects in the same view. ; 3) How to subsequently get the annotations to move in tandem with the ; movement of their associated plot/data objects. ; The specific example demonstrated in this file is one of custom positioning ; a colorbar to be vertically oriented standing at the lower right-hand corner ; of the contour it is annotating. ; 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 'Insert->Colorbar' ; event that we can see on the iContour GUI. ; Let's assume you are relatively knew 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 translating any ID into an object ; reference. 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 coordinates for the boundaries of the plot axes? ; 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 the best 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 margin 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 we could also ; calculate a 'dz' with element [3,2] of the transform matrices. But ; we now have all we 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) ; * 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.