### SlopeAspectGraphTip.sml ### Display Control Script that computes slope and aspect for ### the cursor position from an elevation raster (first layer in ### the group) and plots them graphically in the GraphTip. ### Dimensions of the GraphTip are computed dynamically based on ### the dimensions of the slope triangle and aspect pointer graphics. ### Drawing area coordinates for GraphTip are in screen pixels with ### 0,0 at upper left corner, x positive to right, y positive down. class GRDEVICE_MEM_RGB24 imagedev; ## color rendering device in memory for drawing GraphTip class GRDEVICE_MEM_BINARY maskdev; ## transparency mask in memory for GraphTip class GC gc; ## graphics context for GraphTip class GRE_GROUP group; ### variables for DEM raster class GRE_LAYER_RASTER DEM_layer; class RASTER DEM; class TRANSPARM trans; ## coordinate transformation parameters class POINT2D ptLayer; ## class for layer coordinates of cursor position numeric lin, col; ## current line and column position numeric w, h; ## cell size (width and height) numeric nullDEM; ## null value for DEM numeric dzX, dzY; ## derivatives of Z in X and Y directions numeric slope, aspect; ### variables for GraphTip numeric height, width; # dimensions of drawing area class POINT2D offset; # offset of GraphTip from cursor string aspect$; # aspect value string numeric aspectDrawAngle; # angle used for drawing aspect arrow class POINT2D center; # position of the center of rotation of the aspect arrow array numeric x_points[3]; ## arrays to hold x and y coordinates of the vertices of array numeric y_points[3]; ## the triangle graphic that depicts the slope class POINT2D arrowEnd; ## position used to draw arrow head for aspect pointer numeric tribaseY; ## y-position of base of slope triangle graphic numeric baseline, triHeight; ## width and height of triangle (in screen pixels) numeric aspHeight; ## height needed for aspect pointer (in screen pixels) ### procedure called when group or layout is initialized proc OnInitialize () { offset.x = 15; ## set offset of GraphTip from cursor position offset.y = 15; ## (down and to the right) } ### procedure called when View is created for group proc OnLayoutDrawEnd ( class GRE_LAYOUT layout, class GRE_VIEW view ) { group = layout.GetGroupByName("Kabul Maps"); DEM_layer = group.ActiveLayer; ## get first layer in group DispGetRasterFromLayer(DEM, DEM_layer); ## get raster variable for DEM w = ColScale(DEM); ## get line and column cell size h = LinScale(DEM); nullDEM = NullValue(DEM); ## get null value for DEM view.ActivateToolName("zoom_in"); } ### function called when datatip event is triggered func OnViewDataTipShowRequest ( class GRE_VIEW view, ## predefined class variables class POINT2D point, class TOOLTIP datatip ) { numeric retval = 1; ## in GraphTip use only what is created by script trans = view.GetTransLayerToScreen(DEM_layer, 1); ## transform from screen to layer ptLayer = trans.ConvertPoint2DFwd(point); ## cursor position in layer coordinates lin = floor(ptLayer.y); ## line and column position of DEM cell under cursor col = floor(ptLayer.x); if ( DEM[lin,col] <> nullDEM ) { ## if cursor is not over a null cell ### compute x and y derivatives and slope dzX = ( DEM[lin, col + 1] - DEM[lin, col - 1] ) / (2 * w); dzY = ( DEM[lin - 1, col] - DEM[lin + 1, col] ) / (2 * h); slope = atand( sqrt( sqr(dzX) + sqr(dzY) ) ); ### compute dimensions of slope triangle graphic baseline = 40 * cosd(slope); triHeight = baseline * tand(slope); tribaseY = 17 + round(triHeight); ### compute aspect if (slope == 0) { ## aspect is undefined for flat areas; no pointer needed aspect$ = "Undefined"; aspHeight = 5; ## set drawing height for area where arrow would otherwise be drawn } else { if (dzY != 0) { ## check for division by zero aspect = deg * atan2(-dzX, -dzY); if (aspect < 0 ) then aspect += 360; } else aspect = 90; ## when dzY = 0 aspect$ = sprintf("%.1f deg", aspect); ## create aspect label string aspectDrawAngle = (aspect - 90); ## drawing angle for aspect pointer aspHeight = round( abs( 18 * sind(aspectDrawAngle) ) ); ## height of area pointer will be drawn in if (aspHeight < 5) then aspHeight = 5; ## minimum drawing height for pointer area } ### compute dimensions of GraphTip drawing area based on ### triangle graphic and aspect pointer dimensions width = 54; ## width of drawing area center.x = width / 2; ## position of center for rotating pointer center.y = tribaseY + 35 + aspHeight; height = center.y + aspHeight + 18; ## height of drawing area ### create GraphTip drawing area with specified dimensions imagedev.Create(height,width); maskdev.Create(height,width); ### begin drawing GraphTip elements gc = imagedev.CreateGC(); ### create graphics context for GraphTip gc.SetColorRGB(100,100,67,100); gc.FillRect(0, 0, width, height); ## yellow background rectangle for GraphTip gc.SetColorName("black"); gc.DrawRect(0, 0, width - 1, height - 1); ## draw black frame around GraphTip gc.DrawTextSetFont("ARIAL.TTF"); gc.DrawTextSetHeightPixels(10); gc.TextStyle.RoundWidth = 1; ### draw Slope and Aspect titles gc.DrawTextSimple("Slope:", 12, 12); gc.DrawTextSimple("Aspect:", 10, tribaseY + 30); ### draw slope graphic (right triangle) and value label ### compute coordinates for ends of baseline and store in arrays x_points[1] = center.x - baseline / 2; x_points[2] = center.x + baseline / 2; y_points[1] = tribaseY; y_points[2] = tribaseY; if (slope < 5) { # draw horizontal line instead of triangle gc.MoveTo(x_points[1], y_points[1]); gc.DrawTo(x_points[2], y_points[2]); } else { x_points[3] = center.x + baseline / 2; ## x-coord of top vertex of triangle y_points[3] = tribaseY - triHeight; # y-coordinate of top vertex of triangle ### draw light blue slope triangle gc.SetColorRGB(70, 85, 100, 100); gc.DrawPolyLine(x_points, y_points, 3); gc.FillPolyLine(x_points, y_points, 3); ### draw black line along slope (hypotenuse of right triangle) gc.MoveTo(x_points[1], y_points[1]); ## move to lower left triangle vertex gc.SetColorRGB(0, 0, 0, 100); gc.DrawTo(x_points[3], y_points[3]); ## draw line to top vertex } ### draw text for slope value below triangle gc.DrawTextSimple( sprintf("%.1f deg", slope), 7, tribaseY + 12); ### draw the aspect pointer (line with arrowhead added) and label if (slope > 0) { ### find and store coordinates of end of pointer line arrowEnd.x = center.x + 18 * cosd(aspectDrawAngle); arrowEnd.y = center.y + 18 * sind(aspectDrawAngle); ### move to start of pointer line and draw to end gc.MoveTo( center.x - 16 * cosd(aspectDrawAngle), center.y - 16 * sind(aspectDrawAngle) ); gc.SetColorRGB(100,0,0,100); gc.DrawTo(arrowEnd.x, arrowEnd.y ); ### draw arrowhead gc.DrawArrow(arrowEnd.x, arrowEnd.y, aspectDrawAngle, 6, 30, "Open"); ### draw small red circle at center of rotation of pointer gc.SetColorRGB(0,0,0,100); gc.FillCircle(center.x, center.y, 2); } ### draw text with aspect value under pointer gc.DrawTextSimple(aspect$, 5, center.y + aspHeight + 12); ### set the rendered image and mask as source for the GraphTip datatip.SetImageTip(imagedev, maskdev, offset); } else ## if outside DEM or on null cell then retval = -1; ## don't show any datatip return (retval); }