; docformat = 'rst' ; ; NAME: ; cgMapVector ; ; PURPOSE: ; This object allows vectors (arrows) to be placed as annotations on map ; projections created with the cgMap coordinate object. ; ;******************************************************************************************; ; ; ; Copyright (c) 2011, by Fanning Software Consulting, Inc. All rights reserved. ; ; ; ; Redistribution and use in source and binary forms, with or without ; ; modification, are permitted provided that the following conditions are met: ; ; ; ; * Redistributions of source code must retain the above copyright ; ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; ; notice, this list of conditions and the following disclaimer in the ; ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ; ; contributors may be used to endorse or promote products derived from this ; ; software without specific prior written permission. ; ; ; ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ; ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ; ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ; ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ; ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;******************************************************************************************; ; ;+-------------------------------------------------------------------------- ; This object allows vectors (arrows) to be placed as annotations on map ; projections created with the cgMap coordinate object. ; ; :Categories: ; Graphics, Map Projections ; ; :Author: ; FANNING SOFTWARE CONSULTING:: ; David W. Fanning ; 1645 Sheely Drive ; Fort Collins, CO 80526 USA ; Phone: 970-221-0438 ; E-mail: david@idlcoyote.com ; Coyote's Guide to IDL Programming: http://www.idlcoyote.com ; ; :History: ; Change History:: ; Written by David W. Fanning, 21 November 2011. ; Tested and bugs fixed. 17 Sept 2012. DWF. ; Bug fix in draw method when passing lat/lon vectors. 6 Jan 2013. DWF. ; Added PALETTE keyword to allow the vectors to be drawn in colors scaled ; to vector magnitude. 6 Jan 2012. DWF. ; The CLIP keyword was not working correctly and was fixed 29 April 2013. DWF. ; ; ; :Copyright: ; Copyright (c) 2011, Fanning Software Consulting, Inc. ;- ;+-------------------------------------------------------------------------- ; The initialization method for the object. ; ; :Params: ; mapCoord: in, required, type=object ; A map coordinate object that will set up a map coordinate data space. ; Required to convert lat/lon values to projected meter space. A cgMap object. ; ; :Keywords: ; addcmd: in, optional, type=boolean, default=0 ; If this keyword is set, the object is added to the resizeable graphics ; window, cgWindow. The DRAW method of the object is called in cgWindow. ; clip: in, optional, type=fltarr(4) ; The coordinates of a rectangle used to clip the graphics output. ; The rectangle is specified as a vector of the form [X0, Y0, X1, Y1], ; giving coordinates of the lower left and upper right corners, ; respectively. The default clipping rectangle is the plot window set ; up by the cgMap object. ; color: in, optional, type=string, default="opposite" ; The name of the color to draw the arrows lines in. ; hsize: in, optional, type=float, default=0.35 ; The value of this keyword sets the length of the arrowhead. See the documenation ; for the ARROW command in IDL for further explanation. ; lats: in, optional, type=float ; The latitude values where the vector is to be drawn. ; length, in, optional, type=float ; The length of the UV vectors. The default value calculates a maximum length, ; which is the larger of either the latitude or longitude range. This value is ; then divided by 100. To scale the UV values, the values are divided by the ; maximum magnitude of the UV vectors and then multiplied by the length. The code ; looks like this for the default case:: ; maxlength = Max( [Max(lons)-Min(lons), Max(lats)-Min(lats)] ) ; length = maxlength / 100.0 ; maxMagnitude = Max(Sqrt(u^2 + v^2)) ; uscaled = (u/maxMagnitude) * length ; vscaled = (v/maxMagnitude) * length ; The default length value is likely to be too large for polar plots, but seems ; adequate for other map projections. If you need to adjust the length, get the ; current length with the GetProperty method and the LENGTH keyword, and adjust ; accordingly. The length is not set finally, until the vectors are first drawn. ; linestyle: out, optional, type=integer, default=1 ; Set this keyword to the type of linestyle desired. See Graphics Keywords in ; the on-line help for additional information. ; lons: in, optional, type=float ; The longitude values where the vector is to be drawn. ; noclip: in, optional, type=boolean, default=0 ; Set this keyword to supress clipping of the plot. ; palette: in, optional, type=byte ; A (256x3) color palette containing the RGB color vectors to use for coloring the vectors ; according to the magitude of the vectors. If the color palette is not 256 colors in length ; then the magitude is scaled into the number of colors available. If a color palette is ; used, then the `Color` keyword is ignored. ; solid: in, optional, type=boolean, default=0 ; Set this keyword to draw solid arrow heads. ; t3d: in, optional, type=boolean, default=0 ; Set this graphics keyword if you wish to draw using the T3D transformation matrix. ; thick: in, optional, type=integer, default=1 ; Set this keyword to the thickness of the line used to draw the grid. ; umagnitude: in, optional, type=float ; The magnitude of the vector in the U direction. ; uvcoords: in, optional, type=boolean, default=0 ; Set this keyword if the LONS and LATS are specified in UV (XY) coordinates, rather than ; longitude and latitude coordinates. ; vmagnitude: in, optional, type=float ; The magnitude of the vector in the V direction. ; zvalue: in, optional, type=float, default=0.0 ; Set this keyword to the ZVALUE where the output should be drawn. ; _extra: in, optional ; Any keywords appropriate for superclass objects are also permitted. ; ;--------------------------------------------------------------------------- FUNCTION cgMapVector::INIT, mapCoord, $ ADDCMD=addcmd, $ CLIP=clip, $ COLOR=color, $ HSIZE=hsize, $ LATS=lats, $ LENGTH=length, $ LINESTYLE=linestyle, $ LONS=lons, $ NOCLIP=noclip, $ PALETTE=palette, $ SOLID=solid, $ T3d=t3d, $ THICK=thick, $ UMAGNITUDE=u, $ UVCOORDS=uvcoords, $ VMAGNITUDE=v, $ ZVALUE=zvalue, $ _EXTRA=extra ; Error handling Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel void = cgErrorMsg() RETURN, 0 ENDIF ; Make sure you have a valid map object or there is no point in going ahead. IF ~Obj_Valid(mapCoord) THEN Message, 'A valid map object is required to create a cgMapPlotS object.' ; Initialize superclass object, ok = self -> cgContainer::INIT( _EXTRA=extra) IF ~ok THEN RETURN, 0 ; Default values. SetDefaultValue, color, 'White' SetDefaultValue, hsize, -0.35 SetDefaultValue, length, !Values.F_NAN SetDefaultValue, linestyle, 0 SetDefaultValue, noclip, 1 SetDefaultValue, solid, 0 SetDefaultValue, t3d, 0 SetDefaultValue, thick, 1.0 SetDefaultValue, uvcoords, 0B SetDefaultValue, zvalue, 0.0 IF N_Elements(clip) NE 0 THEN self.clip = clip self.color = color self.hsize = hsize self.length = length self.linestyle = linestyle self.noclip = noclip self.solid = solid self.t3d = t3d self.thick = thick self.uvcoords = uvcoords self.zvalue = zvalue IF N_Elements(lons) EQ 0 $ THEN self.lons = Ptr_New(/ALLOCATE_HEAP) $ ELSE self.lons = Ptr_New(lons) IF N_Elements(lats) EQ 0 $ THEN self.lats = Ptr_New(/ALLOCATE_HEAP) $ ELSE self.lats = Ptr_New(lats) IF N_Elements(u) EQ 0 $ THEN self.u = Ptr_New(/ALLOCATE_HEAP) $ ELSE self.u = Ptr_New(u) IF N_Elements(v) EQ 0 $ THEN self.v = Ptr_New(/ALLOCATE_HEAP) $ ELSE self.v = Ptr_New(v) ; Store the map object. self.mapCoord = mapCoord ; Do you have a color palette? IF N_Elements(palette) NE 0 THEN BEGIN self.color = "" s = Size(palette, /DIMENSIONS) IF s[1] GT s[0] THEN palette = Transpose(palette) s = Size(palette, /DIMENSIONS) ncolors = s[0] self.palette = Ptr_New(palette) self.magcolors = Ptr_New(BytScl(Sqrt((*self.v)^2 + (*self.u)^2), TOP=ncolors-1)) ENDIF ; Need to add this command to a resizeable cgWindow? IF Keyword_Set(addcmd) THEN BEGIN window = cgQuery(/Current, OBJECT=winObject) IF Obj_Valid(winObject) THEN BEGIN cgWindow, 'Draw', self, /Method, /AddCmd ENDIF ELSE BEGIN cgWindow, 'Draw', self, /Method ENDELSE ENDIF RETURN, 1 END ;+ ; This is a heavily modified IDL ARROW procedure, with extra keywords added ; and the COLOR keyword modified to accept color names. It assumes drawing ; in the device coordinate space, unless the DATA or NORMALIZED keywords ; are set. ; ; Copyright (c) 1993-2004, Research Systems, Inc. All rights reserved. ; ; :Params: ; x0: in, required, type=float ; The X value at the butt end of the arrow. ; x1: in, required, type=float ; The X value at the tip end of the arrow. ; y0: in, required, type=float ; The Y value at the butt end of the arrow. ; y1: in, required, type=float ; The Y value at the tip end of the arrow. ; ; :Keywords: ; color: in, optional, type=string, default="opposite" ; The name of the color to draw the grid lines in. ; data: in, optional, type=boolean, default=0 ; Set this keyword to draw in the data coordinate space. ; linestyle: in, optional, type=integer, default=0 ; The graphics linestyle to draw the vector in. ; normalized: in, optional, type=boolean, default=0 ; Set this keyword to draw in the normalized data coordinate space. ; thick: in, optional, type=integer, default=1 ; Set this keyword to the thickness of the line used to draw the grid. ; solid: in, optional, type=boolean, default=0 ; Set this keyword to fill the arrow head with a solid color. Otherwise, ; draw the arrow head as an outline. ; _extra: in, optional ; Any keywords appropriate PlotS or PolyFill. ;- PRO cgMapVector::DrawArrow, x0, y0, x1, y1, $ CLIP=clip, $ COLOR = color, $ DATA = data, $ HSIZE = hsize, $ HTHICK = hthick, $ LINESTYLE=linestyle, $ NORMALIZED = norm, $ THICK = thick, $ SOLID = solid, $ _EXTRA=extra COMPILE_OPT idl2 ; Error handling Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel void = cgErrorMsg() RETURN ENDIF ; Set up keyword params IF N_Elements(thick) EQ 0 THEN thick = 1. IF N_Elements(hthick) EQ 0 THEN hthick = thick ; Head size in device units IF N_Elements(hsize) EQ 0 THEN arrowsize = !d.x_size/50. * (hthick/2. > 1) $ ELSE arrowsize = Float(hsize) IF N_Elements(color) EQ 0 THEN color = "opposite" ; If arrowsize GT 15, THEN use 20% arrow. Otherwise use 30%. IF arrowsize LT 15 THEN BEGIN mcost = -0.866D sint = 0.500D msint = -sint ENDIF ELSE BEGIN mcost = - 0.939693D sint = 0.342020D msint = -sint ENDELSE ; Do this in decomposed color, if possible. cgSetColorState, 1, CURRENT=currentState FOR i = 0L, N_Elements(x0)-1 DO BEGIN ;Each vector ; Clip the vectors. IF ~Keyword_Set(noclip) THEN BEGIN IF (x0 LT clip[0]) || (x0 GT clip[2]) || (y0 LT clip[1]) || (y0 GT clip[3]) THEN Continue x1 = clip[0] > x1 < clip[2] y1 = clip[1] > y1 < clip[3] ENDIF ; Convert to DEVICE coordinates. IF Keyword_Set(data) THEN $ ;Convert? p = Convert_Coord([x0[i],x1[i]],[y0[i],y1[i]], /DATA, /TO_DEVICE) $ ELSE IF Keyword_Set(norm) THEN $ p = Convert_Coord([x0[i],x1[i]],[y0[i],y1[i]], /NORMAL, /TO_DEVICE) $ ELSE p = [[x0[i], y0[i]],[x1[i], y1[i]]] xp0 = p[0,0] xp1 = p[0,1] yp0 = p[1,0] yp1 = p[1,1] dx = xp1 - xp0 dy = yp1 - yp0 zz = SQRT(dx^2d + dy^2d) ;Length IF zz gt 0 THEN BEGIN dx = dx/zz ;Cos th dy = dy/zz ;Sin th ENDIF ELSE BEGIN dx = 1. dy = 0. zz = 1. ENDELSE IF arrowsize gt 0 THEN a = arrowsize $ ;a = length of head ELSE a = -zz * arrowsize xxp0 = xp1 + a * (dx*mcost - dy * msint) yyp0 = yp1 + a * (dx*msint + dy * mcost) xxp1 = xp1 + a * (dx*mcost - dy * sint) yyp1 = yp1 + a * (dx*sint + dy * mcost) IF Keyword_Set(solid) THEN BEGIN ;Use polyfill? b = a * mcost*.9d ;End of arrow shaft (Fudge to force join) Plots, [xp0, xp1+b*dx], [yp0, yp1+b*dy], /DEVICE, $ COLOR = cgColor(color), THICK = thick, LINESTYLE=linestyle, _Extra=extra Polyfill, [xxp0, xxp1, xp1, xxp0], [yyp0, yyp1, yp1, yyp0], $ /DEVICE, COLOR = cgColor(color) ENDIF ELSE BEGIN Plots, [xp0, xp1], [yp0, yp1], /DEVICE, COLOR=cgColor(color), THICK=thick, $ LINESTYLE=linestyle, _Extra=extra Plots, [xxp0,xp1,xxp1],[yyp0,yp1,yyp1], /DEVICE, COLOR=cgColor(color), $ THICK=hthick, LINESTYLE=linestyle, _Extra=extra ENDELSE ENDFOR ; Restore color state. cgSetColorState, currentState END ;+-------------------------------------------------------------------------- ; Draws the vectors on the map projection. ;--------------------------------------------------------------------------- PRO cgMapVector::Draw ; Error handling Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel void = cgErrorMsg() RETURN ENDIF ; You have to have data to plot. If not exit quietly. IF (N_Elements(*self.lons) EQ 0) OR (N_Elements(*self.lats) EQ 0) THEN RETURN IF (N_Elements(*self.u) EQ 0) OR (N_Elements(*self.v) EQ 0) THEN RETURN ; If the vectors don't all have the same number of elements, there is an error. IF N_Elements(*self.lons) NE N_Elements(*self.lats) THEN BEGIN Message, 'The number of elements in the latitude and longitude arrays must be the same.' ENDIF IF N_Elements(*self.u) NE N_Elements(*self.v) THEN BEGIN Message, 'The number of elements in the U and V arrays must be the same.' ENDIF IF N_Elements(*self.lons) NE N_Elements(*self.v) THEN BEGIN Message, 'The number of elements in the lon, lat, u, and v arrays must be the same.' ENDIF ; Find a map structure, IF you can. IF Obj_Valid(self.mapCoord) THEN BEGIN mapStruct = self.mapCoord -> GetMapStruct() self.mapCoord -> Draw, /NoGraphics ENDIF ELSE Message, 'There is no valid map object from which a map structure can be obtained.' ; If you have a map structure, then determine if the locations to plot ; are in lat/lon or UV coordinate space. The MapCoord object sets up ; a UV coordinate space. The locations to be plotted here are in lat/lon ; space, so they have to be converted to XY space to be plotted. IF N_Elements(mapStruct) NE 0 THEN BEGIN ; If the "lons and lats" are already in UVCOORDS, leave them alone. IF self.uvcoords THEN BEGIN lon = *self.lons lat = *self.lats ENDIF ELSE BEGIN ; Otherwise, convert them, since the map is *always* in UVCoords. uv = MAP_PROJ_FORWARD(*self.lons, *self.lats, MAP_STRUCTURE=mapStruct) lon = Reform(uv[0,*]) lat = Reform(uv[1,*]) ENDELSE ENDIF ELSE BEGIN lon = *self.lons lat = *self.lats ENDELSE ; Do we have to assign a value to length? IF ~Finite(self.length) THEN BEGIN maxlen = Max( [Max(*self.lons)-Min(*self.lons), Max(*self.lats)-Min(*self.lats)] ) length = maxlen / 100.0 ENDIF ELSE length = self.length Print, 'Vector Length: ', length ; Scale the U and V values by the length. maxmag = Max(Sqrt(*self.u^2 + *self.v^2)) uscaled = (*self.u/maxmag) * length vscaled = (*self.v/maxmag) * length ; If clip is not defined, then set it here. IF Total(self.clip) EQ 0 $ THEN clip = [!X.CRange[0], !Y.CRange[0], !X.CRange[1], !Y.CRange[1]] $ ELSE clip = self.clip ; Load colors if you have them. IF Ptr_Valid(self.palette) THEN BEGIN TVLCT, r, g, b, /Get TVLCT, *self.palette ENDIF ; Calculate the endpoints of the arrow and draw it. FOR j=0L,N_Elements(*self.u)-1 DO BEGIN x0 = (*self.lons)[j] y0 = (*self.lats)[j] x1 = x0 + uscaled[j] y1 = y0 + vscaled[j] xhalf = (x1-x0)/2.0 yhalf = (y1-y0)/2.0 x0 = x0 - xhalf y0 = y0 - yhalf x1 = x1 - xhalf y1 = y1 - yhalf uv = self.mapCoord -> Forward([x0,x1], [y0,y1]) x0 = uv[0,0] x1 = uv[0,1] y0 = uv[1,0] y1 = uv[1,1] IF self.color EQ "" THEN color = (*self.magcolors)[j] ELSE color = self.color self -> DrawArrow, x0, y0, x1, y1, HSIZE=self.hsize, CLIP=clip, THICK=self.thick, $ HTHICK=self.thick, LENGTH=length, COLOR=color, SOLID=self.solid, $ _EXTRA=extrakeywords, /DATA, LINESTYLE=self.linestyle ENDFOR IF Ptr_Valid(self.palette) THEN TVLCT, r, g, b END ;+-------------------------------------------------------------------------- ; This method allows the user to get various properties of the object. ; The same keywords that are used for the INIT method can be used here. ; ; :Keywords: ; clip: out, optional, type=fltarr(4) ; The coordinates of a rectangle used to clip the graphics output. ; The rectangle is specified as a vector of the form [X0, Y0, X1, Y1], ; giving coordinates of the lower left and upper right corners, ; respectively. The default clipping rectangle is the plot window set ; up by the cgMap object. ; color: out, optional, type=string, default="opposite" ; The name of the color to draw the grid lines in. ; hsize: out, optional, type=float, default=0.35 ; The value of this keyword sets the length of the arrowhead. See the documenation ; for the ARROW command ind IDL for further explanation. ; lats: out, optional, type=float ; The latitude values where the vector is to be drawn. ; length, out, optional, type=float ; The U and V vectors are mutiplied by LENGTH before they are used ; to calculate the (x1,y1) endpoint of the vector. By default, the length is set ; to 1/100th of the XRANGE of the MapCoord object. This means that the maximum ; length of a vector will be approximately LENGTH * SQRT(2). ; linestyle: out, optional, type=integer, default=1 ; Set this keyword to the type of linestyle desired. See Graphics Keywords in ; the on-line help for additional information. ; lons: out, optional, type=float ; The longitude values where the vector is to be drawn. ; noclip: out, optional, type=boolean, default=0 ; Set this keyword to supress clipping of the plot. ; mapcoord: out, optional, type=object ; The map coordinate for the object. ; solid: out, optional, type=boolean ; This keyword is set if solid arrow heads are currently being drawn. ; t3d: out, optional, type=boolean, default=0 ; Set this graphics keyword if you wish to draw using the T3D transformation matrix. ; thick: out, optional, type=integer, default=1 ; Set this keyword to the thickness of the line used to draw the grid. ; umagnitude: out, optional, type=float ; The magnitude of the vector in the U direction. ; uvcoords: out, optional, type=boolean, default=0 ; Set this keyword if the LONS and LATS are specified in UV (XY) coordinates, rather than ; longitude and latitude coordinates. ; vmagnitude: out, optional, type=float ; The magnitude of the vector in the V direction. ; zvalue: out, optional, type=float, default=0.0 ; Set this keyword to the ZVALUE where the output should be drawn. ; _ref_extra: in, optional ; Any keywords appropriate for superclass objects are also permitted. ; ;----------------------------------------------------------------------------------------------- PRO cgMapVector::GetProperty, $ CLIP=clip, $ COLOR=color, $ HSIZE=hsize, $ LATS=lats, $ LENGTH=length, $ LINESTYLE=linestyle, $ LONS=lons, $ MAPCOORD=mapcoord, $ NOCLIP=noclip, $ SOLID=solid, $ T3D=t3d, $ THICK=thick, $ UMAGNITUDE=u, $ UVCOORDS=uvcoords, $ VMAGNITUDE=v, $ ZVALUE=zvalue, $ _REF_EXTRA=extra ; Error handling Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel void = cgErrorMsg() RETURN ENDIF clip = self.clip color = self.color hsize = self.hsize length = self.length linestyle = self.linestyle noclip = self.noclip solid = self.solid t3d = self.t3d thick = self.thick uvcoords = self.uvcoords IF Arg_Present(lats) THEN lats = *self.lats IF Arg_Present(lons) THEN lons = *self.lons IF Arg_Present(u) THEN u = *self.u IF Arg_Present(v) THEN v = *self.v zvalue = self.zvalue mapCoord = self.mapCoord IF N_Elements(extra) NE 0 THEN self -> cgContainer::GetProperty, _EXTRA=extra END ;+-------------------------------------------------------------------------- ; This method allows the user to set various properties of the object. ; The same keywords that are used for the INIT method can be used here. ; ; :Keywords: ; addcmd: in, optional, type=boolean, default=0 ; If this keyword is set, the object is added to the resizeable graphics ; window, cgWindow. The DRAW method of the object is called in cgWindow. ; clip: in, optional, type=fltarr(4) ; The coordinates of a rectangle used to clip the graphics output. ; The rectangle is specified as a vector of the form [X0, Y0, X1, Y1], ; giving coordinates of the lower left and upper right corners, ; respectively. The default clipping rectangle is the plot window set ; up by the cgMap object. ; color: in, optional, type=string, default="opposite" ; The name of the color to draw the grid lines in. ; hsize: in, optional, type=float, default=0.35 ; The value of this keyword sets the length of the arrowhead. See the documenation ; for the ARROW command ind IDL for further explanation. ; lats: in, optional, type=float ; The latitude values where the vector is to be drawn. ; length, in, optional, type=float ; The U and V vectors are mutiplied by LENGTH before they are used ; to calculate the (x1,y1) endpoint of the vector. By default, the length is set ; to 1/100th of the XRANGE of the MapCoord object. This means that the maximum ; length of a vector will be approximately LENGTH * SQRT(2). ; linestyle: out, optional, type=integer, default=1 ; Set this keyword to the type of linestyle desired. See Graphics Keywords in ; the on-line help for additional information. ; lons: in, optional, type=float ; The longitude values where the vector is to be drawn. ; noclip: in, optional, type=boolean, default=0 ; Set this keyword to supress clipping of the plot. ; mapcoord: in, optional, type=object ; The map coordinate for the object. ; palette: in, optional, type=byte ; A (256x3) color palette containing the RGB color vectors to use for coloring the vectors ; according to the magitude of the vectors. If the color palette is not 256 colors in length ; then the magitude is scaled into the number of colors available. If a color palette is ; used, then the `Color` keyword is ignored. ; solid: in, optional, type=boolean, default=0 ; Set this keyword to draw solid arrow heads. ; t3d: in, optional, type=boolean, default=0 ; Set this graphics keyword if you wish to draw using the T3D transformation matrix. ; thick: in, optional, type=integer, default=1 ; Set this keyword to the thickness of the line used to draw the grid. ; umagnitude: in, optional, type=float ; The magnitude of the vector in the U direction. ; uvcoords: in, optional, type=boolean, default=0 ; Set this keyword if the LONS and LATS are specified in UV (XY) coordinates, rather than ; longitude and latitude coordinates. ; vmagnitude: in, optional, type=float ; The magnitude of the vector in the V direction. ; zvalue: in, optional, type=float, default=0.0 ; Set this keyword to the ZVALUE where the output should be drawn. ; _extra: in, optional ; Any keywords appropriate for superclass objects are also permitted. ; ;----------------------------------------------------------------------------------------------- PRO cgMapVector::SetProperty, $ ADDCMD=addcmd, $ CLIP=clip, $ COLOR=color, $ HSIZE=hsize, $ LATS=lats, $ LENGTH=length, $ LINESTYLE=linestyle, $ LONS=lons, $ MAPCOORD=mapCoord, $ NOCLIP=noclip, $ PALETTE=palette, $ SOLID=solid, $ T3D=t3d, $ THICK=thick, $ UMAGNITUDE=u, $ UVCOORDS=uvcoords, $ VMAGNITUDE=v, $ ZVALUE=zvalue, $ _EXTRA=extra ; Error handling Catch, theError IF theError NE 0 THEN BEGIN Catch, /Cancel void = cgErrorMsg() RETURN ENDIF IF N_Elements(lon) NE 0 THEN BEGIN ;print, 'lon:', lon *self.lons = lons ENDIF IF N_Elements(lat) NE 0 THEN BEGIN *self.lats = lats ;print, 'lat:', lats ENDIF IF N_Elements(u) NE 0 THEN BEGIN ;print, 'u:', u *self.u = u ENDIF IF N_Elements(v) NE 0 THEN BEGIN *self.v = v ;print, 'v', v ENDIF IF N_Elements(clip) NE 0 THEN self.clip = clip IF N_Elements(color) NE 0 THEN self.color = color IF N_Elements(hsize) NE 0 THEN self.hsize = hsize IF N_Elements(length) NE 0 THEN self.length = length IF N_Elements(mapCoord) NE 0 THEN self.mapCoord = mapCoord IF N_Elements(linestyle) NE 0 THEN self.linestyle = linestyle IF N_Elements(noclip) NE 0 THEN self.noclip = noclip IF N_Elements(solid) NE 0 THEN self.solid = Keyword_Set(solid) IF N_Elements(t3d) NE 0 THEN self.t3d = t3d IF N_Elements(thick) NE 0 THEN self.thick = thick IF N_Elements(zvalue) NE 0 THEN self.zvalue = zvalue ; Do you have a color palette? IF N_Elements(palette) NE 0 THEN BEGIN Ptr_Free, self.palette Ptr_Free, self.magcolors self.color = "" s = Size(palette, /DIMENSIONS) IF s[1] GT s[0] THEN palette = Transpose(palette) s = Size(palette, /DIMENSIONS) ncolors = s[0] self.palette = Ptr_New(palette) self.magcolors = Ptr_New(BytScl(Sqrt((*self.v)^2 + (*self.u)^2), TOP=ncolors-1)) ENDIF IF N_Elements(extra) NE 0 THEN self -> cgContainer::SetProperty, _EXTRA=extra END ;+-------------------------------------------------------------------------- ; This is the clean-up routine for the object. ;--------------------------------------------------------------------------- PRO cgMapVector::CLEANUP Ptr_Free, self.lons Ptr_Free, self.lats Ptr_Free, self.u Ptr_Free, self.v Ptr_Free, self.palette Ptr_Free, self.magcolors self -> cgContainer::CLEANUP END ;+-------------------------------------------------------------------------- ; This is the class definition module. ; ; :Params: ; class: out, optional, type=structure ; Occasionally, it is useful to have an object class definition as ; a structure variable. Using this output keyword will allow that. ;--------------------------------------------------------------------------- PRO cgMapVector__DEFINE, class class = { cgMapVector, $ lons: Ptr_New(), $ lats: Ptr_New(), $ u: Ptr_New(), $ v: Ptr_New(), $ length: 0.0D, $ clip: DblArr(4),$ color: "", $ hsize: 0.0, $ linestyle: 0, $ magcolors: Ptr_New(), $ noclip: 0B, $ palette: Ptr_New(), $ solid: 0, $ t3d: 0B, $ thick: 0, $ uvcoords: 0B, $ zvalue: 0.0, $ mapCoord: Obj_New(), $ INHERITS cgContainer $ } END ; -------------------------------------------------------------------------------------