# PopInViewTool.sml # # Sample SML Tool Script. # On left mouse-click, pops in a circular view of another # specified spatial object at the location of the cursor, # similar to a View-in-View. # # Group must have a raster object as the first layer. # Circular pop-in view shows matching area from a raster or # vector object that need not be in the group; object is # selected interactively using a dialog created and opened by # the tool script. # # Author: Jeremy Johnson and Randy Smith # MicroImages, Inc. # 10 December 2004 # The following symbols are predefined # class GRE_VIEW View {use to access the view the tool script is attached to} # class GRE_GROUP Group {use to access the group being viewed if the script is run from a group view} # class GRE_LAYOUT Layout {use to access the layout being viewed if the script is run from a layout view} # numeric ToolIsActive Will be 0 if tool is inactive or 1 if tool is active # The following values are also predefined and are valid when the various On...() # functions are called which deal with pointer and keyboard events. # numeric PointerX Pointer X coordinate within view in pixels # numeric PointerY Pointer Y coordinate within view in pixels # numeric ShiftPressed 1 if key being pressed or 0 if not # numeric CtrlPressed 1 if key being pressed or 0 if not # numeric LeftButtonPressed 1 if left pointer button pressed or 0 if not # numeric RightButtonPressed 1 if right pointer button pressed or 0 if not # numeric MiddleButtonPressed 1 if middle pointer button pressed or 0 if not class GRE_LAYER_RASTER F_layer; class RASTER F, ToolRaster; class VECTOR ToolVector, MaskVector, ExtractedVector; class POLYLINE shape; class TRANSPARM ScreenToLayer, FMapToToolMap; class TRANSPARM FObjToMap, ToolMapToObj; class POINT2D point, centerpoint; class RVC_GEOREFERENCE ToolGeo, FGeo; class GRDEVICE_MEM_RGB24 rasterdev; class GRDEVICE_MEM_GRAY8 maskdev; class GRE_LAYER VectLayer, TestLayer; class OBJECT SelectionObject; numeric height, width, err, polynum; numeric isVector, isRaster; class GC gc, viewgc; class GRE_LAYER VectLayer; func SelectLayer(); ################################################################################ # Procedure called the first time the tool is activated. # If the tool implements a dialog it should be created (but not displayed) here. ################################################################################ proc OnInitialize () { isVector = false; isRaster = false; SelectLayer(); } # end of OnInitialize ##################################################### # Procedure to select the source object for the tool ##################################################### func SelectLayer() { local string filename$, objname$; GetInputObject("Raster,Vector","Select input object", filename$, objname$); if (ObjectNumber(filename$, objname$, "RASTER") > 0) { OpenRaster(ToolRaster, filename$, objname$); isRaster = true; isVector = false; } else if (ObjectNumber(filename$, objname$, "VECTOR") > 0) { OpenVector(ToolVector, filename$, objname$); isRaster = false; isVector = true; } return 0; } #################################################################### # Procedure to create raster image for tool, which is drawn into the # drawing area of the View window. #################################################################### proc RasterTool () { # Set height and width of tool image area (in screen pixels, as a fraction of View dimensions). # Height and width should match. Height must be > 32. height =View.height/6; width = View.width/6; if (height < 32 && width < 32) { height = width = 32; } else { if (height < width) { width = height; } else { height = width; } } ############################################################################ # offset point from cursor position to upper left corner of tool image area. ############################################################################ point.x -= width/2; point.y -= height/2; centerpoint.x = width/2; centerpoint.y = height/2; ############################################### # Set up projection transformations ############################################### ToolGeo.OpenLastUsed(ToolRaster); ToolGeo.GetTransparm(ToolMapToObj, 1, ToolGeo.GetCalibModel() ); FMapToToolMap.OutputCoordRefSys = ToolGeo.GetCoordRefSys(); FGeo.OpenLastUsed(F); FGeo.GetTransparm(FObjToMap, 0, FGeo.GetCalibModel() ); FMapToToolMap.InputCoordRefSys = FGeo.GetCoordRefSys(); ScreenToLayer = View.GetTransLayerToScreen(F_layer, 1); ############################################### # Set up drawing area ############################################### viewgc = CreateGCForDrawingArea(View.DrawingArea); rasterdev.Create(height, width); gc = rasterdev.CreateGC(); ############################################### # Calculate map translations and draw into GC ############################################### class POINT2D SourcePoint, LayerPoint, MapPoint, ToolMapPoint, ToolObjPoint; class COLOR c; class COLORMAP cmap; local numeric x, y; for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { SourcePoint.x = point.x + x; # increment screen position SourcePoint.y = point.y + y; LayerPoint = ScreenToLayer.ConvertPoint2DFwd(SourcePoint); # find position in lin and col of displayed raster equivalent to mouse position + offset of GraphTip lin and col MapPoint = TransPoint2D(LayerPoint, FObjToMap); # convert to map coordinates of displayed raster ToolMapPoint = FMapToToolMap.ConvertPoint2dFwd(MapPoint); # find map coordinates in georeference used by desired tool raster ToolObjPoint = TransPoint2D(ToolMapPoint, ToolMapToObj); # convert map coordinates to lin and col of desired tool raster if (ToolRaster.$Info.Type == "16-bit color RGB") { # get the color from the target cell on the other raster c = UnpackRGB(ToolRaster[ToolObjPoint.y+1, ToolObjPoint.x+1], 16); } else if (ToolRaster.$Info.Type == "16-bit color BGR") { c = UnpackRGB(ToolRaster[ToolObjPoint.y+1, ToolObjPoint.x+1], 16, "BGR"); } else if (ToolRaster.$Info.Type == "24-bit color RGB") { c = UnpackRGB(ToolRaster[ToolObjPoint.y+1, ToolObjPoint.x+1], 24); } else if (ToolRaster.$Info.Type == "24-bit color BGR") { c = UnpackRGB(ToolRaster[ToolObjPoint.y+1, ToolObjPoint.x+1], 24, "BGR"); } else { cmap = ColorMapFromRastVar(ToolRaster); if (cmap != 0) { c = ColorMapGetColor(cmap, ToolRaster[ToolObjPoint.y+1, ToolObjPoint.x+1]); } else { c.red = ToolRaster[ToolObjPoint.y + 1, ToolObjPoint.x + 1]; c.blue = ToolRaster[ToolObjPoint.y + 1, ToolObjPoint.x + 1]; c.green = ToolRaster[ToolObjPoint.y + 1, ToolObjPoint.x + 1]; } } gc.SetColor(c); # set the raster color as the drawing color gc.DrawPoint(x,y); } } ############################################### # Create circular mask ############################################### local numeric radius = (width/2)-1; maskdev.Create(height,width); gc = maskdev.CreateGC(); gc.SetColorRGB(50,50,50,55); gc.FillCircle(centerpoint.y, centerpoint.x, radius); ############################################### # Copy the drawn area into the tool ############################################### class RECT myrect; myrect.x1 = 1; myrect.y1 = 1; myrect.x2 = width-1; myrect.y2 = height-1; viewgc.CopyRect(rasterdev, myrect, point,maskdev); return; } ####################################################################################### # Procedure to extract circular area from source vector to show as tool result in View. # Draws circle in MaskVector to use as extraction boundary; extracted vector is added # to group as a layer ####################################################################################### proc VectorTool () { # create temporary vector objects CreateTempVector(MaskVector,"VectorToolkit,Polygonal", "NoStatusText" ); # to draw circle in for extraction CopySubobjects(ToolVector, MaskVector, "GEOREF"); CreateTempVector(ExtractedVector,"", "NoStatusText"); # extracted vector to display as tool result ############################################### # Set up projections ############################################### ToolGeo.OpenLastUsed(ToolVector); ToolGeo.GetTransparm(ToolMapToObj, 1, ToolGeo.GetCalibModel() ); FMapToToolMap.OutputCoordRefSys = ToolGeo.GetCoordRefSys(); FGeo.OpenLastUsed(F); FGeo.GetTransparm(FObjToMap, 0, FGeo.GetCalibModel() ); FMapToToolMap.InputCoordRefSys = FGeo.GetCoordRefSys(); ############################################### # Apply transformations ############################################### SourcePoint = point; LayerPoint = ScreenToLayer.ConvertPoint2DFwd(SourcePoint); # find position in lin and col of displayed raster MapPoint = TransPoint2D(LayerPoint, FObjToMap); # convert to map coordinates of displayed raster ToolMapPoint = FMapToToolMap.ConvertPoint2dFwd(MapPoint); # find map coordinates in georeference used by tool vector # convert map coordinates to object coordinates of tool vector ToolObjPoint = TransPoint2D(ToolMapPoint, ToolMapToObj); #################################################################### # draw circular polygon in mask vector to use as extraction boundary #################################################################### point =ToolObjPoint; shape.Clear(); # clear previous polyline local class POINT2D circlepoint; # class instance for computed vertex position on circumference of circle local numeric x, y; local numeric radius = 200; # radius of circle in source object coordinates local numeric r2 = radius * radius; point.y += radius/2; # create top half of circle and add to polyline for (x = -radius; x <= radius; x++) { y = sqrt((r2 - x*x) +0.5); circlepoint.x = point.x + x; circlepoint.y = point.y + y; shape.AppendVertex(circlepoint); } # create bottom half of circle and add to polyline for (x = radius; x >= -radius; x--) { y = sqrt((r2 - x*x) +0.5); circlepoint.x = point.x +x; circlepoint.y = point.y -y; shape.AppendVertex(circlepoint); } # close polyline and add it as an element to the MaskVector to use for extraction shape.SetClosed(1); VectorAddPolyLine(MaskVector, shape); ExtractedVector = VectorExtract(MaskVector, ToolVector, "InsideClip"); VectLayer = GroupQuickAddVectorVar(Group, ExtractedVector); View.RedrawDirect("NoBlankScreen"); } # end VectorTool() ######################################################### # Procedure to remove previous vector layer if it exists ######################################################### func RemoveVectorLayer () { local numeric removed = 0; if (VectLayer.Name != "") { TestLayer = Group.FirstLayer; while (removed == 0) { if (TestLayer.Name == "") { removed =1; continue; } if (TestLayer.Name == VectLayer.Name) { Group.RemoveLayer(TestLayer); removed = 2; } TestLayer = TestLayer.NextLayer; } } return removed; } ##################################################################### # Procedure called when user presses 'left' pointer/mouse button. ##################################################################### proc OnLeftButtonPress () { point.x = ceil(PointerX); point.y = ceil(PointerY); # get transparm from screen coordinates to raster layer coordinates ScreenToLayer = View.GetTransLayerToScreen(F_layer, 1); # transform cursor screen coordinates to object coordinates of raster that is first layer in group LayerPoint = ScreenToLayer.ConvertPoint2DFwd(point); local numeric onNull = IsNull( F[LayerPoint.y, LayerPoint.x] ); # check if cursor is on null cell if (isRaster) { View.RestoreAll(); # clear previous tool image from View if (onNull == false) then RasterTool(); # if on non-null cell, show raster tool result } else if (isVector) { local numeric removed = RemoveVectorLayer(); if (removed == 2) then # only redraw if a vector layer was actually removed View.RedrawDirect("NoBlankScreen"); if (onNull == false) then VectorTool(); # if on non-null cell, show vector tool result } else { PopupMessage("Please select an input object"); SelectLayer(); } } ###################################################################### # Procedure called when user presses the 'middle' pointer/mouse button ####################################################################### proc OnMiddleButtonPress() { SelectLayer(); } ##################################################################### # Procedure called when user presses the 'right' pointer/mouse button ##################################################################### proc OnRightButtonPress() { RemoveVectorLayer(); View.RestoreAll(); View.RedrawDirect("NoBlankScreen"); } ####################################################################### # Procedure called when user presses the 'middle' pointer/mouse button ####################################################################### proc OnPointerMoveWithButton () { if (isRaster && LeftButtonPressed == 1) { point.x = ceil(PointerX); point.y = ceil(PointerY); RasterTool(); } } ######################################################################### # Procedure called when tool is activated. # If the tool implements a dialog it should be "managed" (displayed) here. ########################################################################## proc OnActivate () { F_layer = Group.FirstLayer; # get handle for raster that is first layer in group DispGetRasterFromLayer(F, F_layer); } ################################################################## # Alternate OnActivate: ################################################################# # This OnActivate shows how to link the tool directly to one raster rather # than using the selection dialog to choose an input object. # Also note that if using this alternative, the OnMiddleButtonPress function, # which brings up the object selection dialog, should be removed. # # The script can also be set to link directly to one vector. # To do this, ToolVector must point to the desired vector, isVector should # be set to true, isRaster should be set to false # # proc OnActivate () { # F_layer = Group.FirstLayer; # DispGetRasterFromLayer(F, F_layer); # OpenRaster(ToolRaster, _context.ScriptDir + "\\cb_comp.rvc", "_24BIT_RGB"); # isVector = false; # isRaster = true; # } ################################################################