Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
# 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 <shift> key being pressed or 0 if not
# numeric CtrlPressed 1 if <ctrl> 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;
# }
################################################################