PopInViewTool.sml

  Download

More scripts: Display Toolbar

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;
#	}
################################################################