home products news downloads documentation support gallery online maps resellers search
TNTmips Downloads Menu

HOME

CONTACT US

CURRENT RELEASE
  TNT 2013

DEVELOPMENT VERSION
  TNT 2014

TNTmips Pro
PRIOR RELEASES
  TNT 2012

FREE SOFTWARE
  TNTmips Free
  TNTatlas
  TNTsdk

MORE DOWNLOADS
  HASP Key Driver
  Screen Recorder
  TNT Language Kits
  Sample Geodata
  TNT Scripts

DOCUMENTATION
  TNTmips Tutorials
  Tutorial Datasets
  Technical Guides
  Scripts
  Quick Guides

MORE INFO
  Download FAQs
  FTP
  Download Managers
  Find Reseller

SITE MAP


roads_Profile.sml

See other examples and scripts with DataTips and GraphTips ...


#
# This script is meant to be run as a Display control script
#
# Assumptions:
# In the group there are two layers:
# Layer 1: DEM
# Layer 2: Overlaying vector lines
#
# Purpose:
# The script generates graphical image tip displaying a plotted
# profile of the nearest line, using the DEM values for elevation.
#
# TODO:
# If the extents of the nearest line (for which the graph tip is 
# generated) is beyond the extents of the view window, then the
# offset value must be adjusted.
#
class GRDEVICE_MEM_RGB24 imagedev;
class GRDEVICE_MEM_BINARY maskdev;
class GC gc;

class GRE_GROUP group;
class GRE_LAYER_VECTOR vectorLayer;
class GRE_LAYER_RASTER rasterLayer;
class VECTOR lineVector;
class RASTER dem;
class GEOREF vecGeoref;
class TRANSPARM objToMap;

numeric minz, maxz;
numeric leftGraphOffset, bottomGraphOffset=20, rightGraphOffset=5, topGraphOffset=15;
numeric fontHeight = 12;
string message$;

# Initialize the image device
proc OnInitialize ()
{
	imagedev.Create(192, 256);
	maskdev.Create(192, 256);
	maskdev.ClearAll();
}

proc OnLayoutDrawEnd (
   class GRE_LAYOUT layout,
   class GRE_VIEW view
   ) {
	group = layout.GetGroupByName("ImageMaps");
	rasterLayer = group.FirstLayer;
	DispGetRasterFromLayer(dem, rasterLayer);

	vectorLayer = group.LastLayer;
	DispGetVectorFromLayer(lineVector, vectorLayer);
	vecGeoref = GetLastUsedGeorefObject(lineVector);

	class TRANSPARM mapTrans;
	mapTrans.InputProjection = vectorLayer.Projection;
	mapTrans.OutputProjection = rasterLayer.Projection;

#	message$ = "RasterLayer: " + rasterLayer.Name + " \n" + "VectorLayer: " + vectorLayer.Name;
#	PopupMessage(message$);
   }

# Compute the distance between two points
func computeDistance(class POINT2D p1, class POINT2D p2)
{
	return sqrt((p2.x-p1.x)^2 + (p2.y-p1.y)^2);
}

# Determine if the given lin, col is within the raster extents
func isPointInRaster(numeric lin, numeric col)
{
	if (lin<1 || col<1 || lin>NumLins(dem) || col>NumCols(dem)) return 0;
	return 1;
}

# Get the z value
func computeElevation(class POINT2D p)
{
	p = mapTrans.ConvertPoint2DFwd(p);  # convert from vector map coordinates to raster map coordinates

	local class POINT2D obj = MapToObject(GetLastUsedGeorefObject(dem), p.x, p.y, dem);
	obj.x = obj.x + .5; # center of cell
	obj.y = obj.y + .5; # center of cell


	local numeric demValue;
	if(isPointInRaster(obj.y, obj.x)) demValue = dem[obj.y, obj.x];	# y for line, x for column
	else	demValue = null;
	return demValue;
}

# Construct the graph line, x dimension is line distance y is elevation
func class POLYLINE constructGraphLine(class POLYLINE origLine)
{
	local class POLYLINE newLine;
	local class POINT2D tmp;

#	origLine.ConvertForward(mapTrans);

	local numeric i;
	local numeric distance=0;
	local numeric elevation = computeElevation(origLine.GetVertex(0));
	tmp.x = distance;
	tmp.y = elevation;
	newLine.AppendVertex(tmp);

	for i=1 to origLine.GetNumPoints()-1
	{
		distance += computeDistance(origLine.GetVertex(i-1), origLine.GetVertex(i));
		elevation = computeElevation(origLine.GetVertex(i));

		tmp.x = distance;
		tmp.y = elevation;
		newLine.AppendVertex(tmp);
	}
	return newLine;
}

# Determine if the value given is a null value
func isNull(numeric value)
{
	if (IsNull(value)) return 1;
	return value == NullValue(dem);
}

# Get the width from the appropriate drawing device
func getHeight()
{
	return imagedev.GetHeight();
}

# Get the width from the appropriate drawing device
func getWidth()
{
	return imagedev.GetWidth();
}

# Create the GC here using the appropriate drawing device (gc is global)
proc createGC()
{
	if (gc == 0) gc = imagedev.CreateGC();
}

# draw the axes for the graph
proc drawGraphAxes(class POLYLINE graphLine)
{
	# make a greyish-blue background
	local class COLOR textColor;
	gc.DrawTextSetColors(textColor);
	gc.SetColorRGB(255, 255, 255);
	gc.FillRect(0, 0, getWidth(), getHeight());
	gc.SetColorRGB(0, 0, 0);
   gc.DrawRect(0,0, getWidth() - 1, getHeight() - 1);

	# Get the minimum and maximum z values
	minz=9999999; maxz=-9999999;
	local numeric i=0;
	for i=0 to graphLine.GetNumPoints()-1
	{
		local numeric z = graphLine.GetVertex(i).y;
		if (z < minz) minz = z;
		if (z > maxz) maxz = z;
	}

	local string min$ = sprintf("%d", minz);
	local string max$ = sprintf("%d", maxz);
	if (maxz==-9999999) max$ = "null";
	if (minz==9999999) min$ = "null";

	# Draw graph axes
	local numeric size = gc.TextGetWidth(max$);
	leftGraphOffset = size + 5;
	if (maxz == minz) max$ = "";
	local array numeric graphx[3], graphy[3];
	graphx[1] = leftGraphOffset;
	graphy[1] = topGraphOffset;
	graphx[2] = leftGraphOffset;
	graphy[2] = getHeight() - bottomGraphOffset;
	graphx[3] = getWidth() - rightGraphOffset;
	graphy[3] = graphy[2];
	gc.DrawPolyLine(graphx, graphy, 3);

	# Draw text for coordinate and elevation axis labels
	gc.DrawTextSetFont("ARIAL");
	gc.DrawTextSetHeightPixels(fontHeight);

	# draw y axis labels
	gc.DrawTextSimple(max$, 3, graphy[1]+fontHeight/2);
	gc.DrawTextSimple(min$, 3, graphy[2]+fontHeight/2);
	local string ylabel = "elevation (m)";
	gc.DrawTextSimple(ylabel, graphx[1]-4, (graphy[3]-graphy[1])/2+gc.TextGetWidth(ylabel)*3/4, 90);

	# draw x axis labels
	gc.DrawTextSimple("0", graphx[1] - gc.TextGetWidth("0")/2, getHeight()-4);
	local string str$ = sprintf("%d", graphLine.GetVertex(graphLine.GetNumPoints()-1).x);
	gc.DrawTextSimple(str$, getWidth() - gc.TextGetWidth(str$) - 3, getHeight()-4);
	local string xlabel = "distance (m)";
	gc.DrawTextSimple(xlabel, (graphx[3]-graphx[1])/2-gc.TextGetWidth(xlabel)/4, getHeight()-bottomGraphOffset+fontHeight+1);
}

# translate a point on the graphline to image device coordinates for drawing
func class POINT2D transPointToGraph(class POINT2D point, class POLYLINE graphLine)
{
	# get graph extents
	local numeric minx, maxx, miny, maxy;
	minx = leftGraphOffset;
	miny = topGraphOffset;
	maxx = getWidth() - rightGraphOffset;
	maxy = getHeight() - bottomGraphOffset;

	# Get the drawing scale
	local numeric xscale = 0, yscale = 0;
	xscale = (maxx - minx) / abs(graphLine.GetVertex(graphLine.GetNumPoints()-1).x - graphLine.GetVertex(0).x);
	if (maxz != minz) yscale = (maxy - miny) / (maxz - minz);

	point.x = point.x * xscale + leftGraphOffset;
#	if (IsNull(point.y)) point.y=0;
	if (yscale!=0) point.y = getHeight() - ((point.y-minz) * yscale + bottomGraphOffset);
	else point.y = getHeight() - bottomGraphOffset;
	return point;
}

# draw the graph with the given polyline
proc drawGraph(class POLYLINE graphLine, numeric vertexNum)
{
	# Plot out the axes first
	drawGraphAxes(graphLine);

	# Draw the profile
	gc.SetColorRGB(200, 50, 50);
	local class POINT2D linePoint = graphLine.GetVertex(0);

	# Plot point zero
	local class POINT2D graphPoint = transPointToGraph(linePoint, graphLine);
	gc.DrawPoint(graphPoint.x, graphPoint.y);

	# Plot the rest of the points
	local numeric i;
	for i=1 to graphLine.GetNumPoints()-1
	{
		linePoint = graphLine.GetVertex(i);
		graphPoint = transPointToGraph(linePoint, graphLine);

		if (isNull(linePoint.y))
		{
			# if null skip point and move to next
			i++;
#			linePoint = graphLine.GetVertex(i+1);
			while (i (getWidth() - rightGraphOffset - leftGraphOffset)/2)
		{
			gc.DrawTextSimple(elev, leftGraphOffset+1, graphCircle.y-1);	# draw on left
		}
		else
		{
			gc.DrawTextSimple(elev, getWidth() - rightGraphOffset - gc.TextGetWidth(elev)-1, graphCircle.y-1);	# draw on right
		}
	}
}

# Computes the offset to use to prevent graph from obscuring element
func class POINT2D computeOffset(class POLYLINE line, class GRE_VIEW view, class POINT2D cursor)
{
	local class POINT2D offset, imageOffset, extentsOffset, center;
	local class RECT extents = line.ComputeExtents();
	local numeric isUpper = 0, isLeft = 0;
	local numeric pixelOffset = 5;

	center = view.Center;
	center = TransPoint2D(center, ViewGetTransViewToScreen(view));

	if (cursor.y < center.y) isUpper = 1;
	if (cursor.x < center.x) isLeft = 1;

	if (isUpper)	# isUpper half of view, get min y
	{
		if (extents.pt1.y < extents.pt2.y) offset.y = extents.pt1.y;
		else offset.y = extents.pt2.y;
		extentsOffset.y = pixelOffset;
	}
	else	# isLower half of view, get max y
	{
		if (extents.pt1.y > extents.pt2.y) offset.y = extents.pt1.y;
		else offset.y = extents.pt2.y;
		imageOffset.y = -getHeight();
		extentsOffset.y = -pixelOffset;
	}
	if (isLeft)	# isLeft half of view, get max x
	{
		if (extents.pt1.x > extents.pt2.x) offset.x = extents.pt1.x;
		else offset.x = extents.pt2.x;
		extentsOffset.x = pixelOffset;
	}
	else	# isRight half of view, get min y
	{
		if (extents.pt1.x < extents.pt2.x) offset.x = extents.pt1.x;
		else offset.x = extents.pt2.x;
		imageOffset.x = -getWidth();
		extentsOffset.x = -pixelOffset;
	}

	# Get screen pixels
	offset = TransPoint2D(offset, ViewGetTransMapToView(view, vectorLayer.Projection));
	offset = TransPoint2D(offset, ViewGetTransViewToScreen(view));

	# Adjust by cursor position
	offset = offset - cursor;

	# Offset accounting for the size of the image
	offset = offset + imageOffset;

	# Offset from line extents
	offset = offset + extentsOffset;

	return offset;
}

# Convert the polyline from obj to map coordinates
func class POLYLINE convertObjectToMap(class POLYLINE line)
{
	local class POLYLINE ret;
	local class POINT2D obj, map;

	local numeric i;
	for i=0 to line.GetNumPoints()-1
	{
		obj = line.GetVertex(i);
		map = ObjectToMap(lineVector, obj.x, obj.y, vecGeoref);
		ret.AppendVertex(map);
	}

	return ret;
}

# Predefined function called when the cursor pauses triggering a datatip action event
func OnViewDataTipShowRequest(class GRE_VIEW view, class POINT2D point, class TOOLTIP datatip)
{
	datatip.Delay = 500;

	numeric scale = view.CurrentMapScale;
	if (!vectorLayer.IsVisibleAtScale(scale)) return -1;
#	if (scale > 4000000) return -1;

	# Store the cursor position
	local class POINT2D cursor = point;

	# Get the cursor position in map coords
	local class TRANSPARM screenToView = ViewGetTransViewToScreen(view, 1);
	local class TRANSPARM viewToMap = ViewGetTransMapToView(view, vectorLayer.Projection, 1);
	point = TransPoint2D(point, screenToView);
	point = TransPoint2D(point, viewToMap);

	# Translate 16 pixel distance to map projected distance
	local class POINT2D tmppoint0;
	tmppoint0.x = 0; tmppoint0.y = 0;
	tmppoint0 = TransPoint2D(tmppoint0, screenToView);
	tmppoint0 = TransPoint2D(tmppoint0, viewToMap);

	local class POINT2D tmppoint;
	tmppoint.x = sqrt(128); tmppoint.y = sqrt(128);
	tmppoint = TransPoint2D(tmppoint, screenToView);
	tmppoint = TransPoint2D(tmppoint, viewToMap);

	local numeric dist = computeDistance(tmppoint0, tmppoint);

	# Get the line from the cursor position
	local numeric lineNum = FindClosestLine(lineVector, point.x, point.y, vecGeoref, dist);
	if (lineNum == 0) return -1;	# if we are not close enough, don't display graph
	local class POLYLINE line = GetVectorLine(lineVector, lineNum);
	line = convertObjectToMap(line);

	# Highlight the line
	vectorLayer.line.HighlightSingle(lineNum);
#	view.RedrawLayer(vectorLayer); ## demir

	# Get the closest vertex for display
	local numeric vertexNum = line.FindClosestVertex(point);
	# Get the line to graph - x-dimension is distance, y is elevation
	local class POLYLINE graphLine = constructGraphLine(line);

	# Create the graphics context to draw the graph to
	createGC();

	# Draw the graph
	drawGraph(graphLine, vertexNum);

	# Compute Image tip offset and display
	local class POINT2D offset;
	offset = computeOffset(line, view, cursor);
	datatip.SetImageTip(imagedev, maskdev, offset);
	return 1;
}










Back Home ©MicroImages, Inc. 2013 Published in the United States of America
11th Floor - Sharp Tower, 206 South 13th Street, Lincoln NE 68508-2010   USA
Business & Sales: (402)477-9554  Support: (402)477-9562  Fax: (402)477-9559
Business info@microimages.com  Support support@microimages.com  Web webmaster@microimages.com

25 March 2009

page update: 26 May 11