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


utest.sml


# The following symbols are predefined
#    class VIEW View            {use to access the view the tool script is attached to}
#    class GROUP Group          {use to access the group being viewed if the script is run from a group view}
#    class LAYOUT Layout        {use to access the layout being viewed if the script is run from a layout view} 
# 
# The following values are also predefined and are valid when the various On...() 
# functions are called which deal with pointer and keyboard events. 
#    number PointerX            Pointer X coordinate within view in pixels 
#    number PointerY            Pointer Y coordinate within view in pixels 

# Variable declarations
class GRE_GROUP activegroup;
class GRE_LAYER_VECTOR vectorLayer, pointLayer, polyLayer;
class Vector pointVector;
class Vector lineVector;
class Vector polyVector, tmpVector;
class Raster rast;
class REGION2D regionIn, regionOut;
numeric n1=0, n2=0;
class DBTABLEINFO pointTable, polyTable;
class GUI_DLG dlgwin;
class GUI_CTRL widthCtrl, lengthCtrl, pointCtrl, polyCtrl;
numeric ALPHA = .05;
string pointLayerName;
numeric currentRun = 1;

# tables to use for critical U values
numeric MAX_TABLE_SIZE = 20;
array numeric alpha05[MAX_TABLE_SIZE,MAX_TABLE_SIZE];
array numeric alpha01[MAX_TABLE_SIZE,MAX_TABLE_SIZE];

proc popupMessage(numeric n)
{
	PopupMessage(NumToStr(n));
}

# Initialize the critical U values lookup tables for the Mann-Whitney U test
# At the time of this script the tables were available at the following URL:
# http://fsweb.berry.edu/academic/education/vbissonnette/tables/mwu.pdf
proc initCriticalValuesTables()
{
	local numeric s1, s2;
	for s1=1 to MAX_TABLE_SIZE
	{
		for s2=1 to MAX_TABLE_SIZE
		{
			alpha05[s2,s1] = alpha01[s2,s1] = 0;
		}
	}

	# table for alpha = .05 (95%)
	alpha05[3,3]=0; alpha05[3,4]=0; alpha05[3,5]=0; alpha05[3,6]=1; alpha05[3,7]=1; alpha05[3,8]=2; alpha05[3,9]=2; alpha05[3,10]=3; alpha05[3,11]=3; alpha05[3,12]=4; alpha05[3,13]=4; alpha05[3,14]=5; alpha05[3,15]=5; alpha05[3,16]=6; alpha05[3,17]=6; alpha05[3,18]=7; alpha05[3,19]=7; alpha05[3,20]=8;
	alpha05[4,3]=0; alpha05[4,4]=0; alpha05[4,5]=1; alpha05[4,6]=2; alpha05[4,7]=3; alpha05[4,8]=4; alpha05[4,9]=4; alpha05[4,10]=5; alpha05[4,11]=6; alpha05[4,12]=7; alpha05[4,13]=8; alpha05[4,14]=9; alpha05[4,15]=10; alpha05[4,16]=11; alpha05[4,17]=11; alpha05[4,18]=12; alpha05[4,19]=13; alpha05[4,20]=14;
	alpha05[5,3]=0; alpha05[5,4]=1; alpha05[5,5]=2; alpha05[5,6]=3; alpha05[5,7]=5; alpha05[5,8]=6; alpha05[5,9]=7; alpha05[5,10]=8; alpha05[5,11]=9; alpha05[5,12]=11; alpha05[5,13]=12; alpha05[5,14]=13; alpha05[5,15]=14; alpha05[5,16]=15; alpha05[5,17]=17; alpha05[5,18]=18; alpha05[5,19]=19; alpha05[5,20]=20;
	alpha05[6,3]=1; alpha05[6,4]=2; alpha05[6,5]=3; alpha05[6,6]=5; alpha05[6,7]=6; alpha05[6,8]=8; alpha05[6,9]=10; alpha05[6,10]=11; alpha05[6,11]=13; alpha05[6,12]=14; alpha05[6,13]=16; alpha05[6,14]=17; alpha05[6,15]=19; alpha05[6,16]=21; alpha05[6,17]=22; alpha05[6,18]=24; alpha05[6,19]=25; alpha05[6,20]=27;
	alpha05[7,3]=1; alpha05[7,4]=3; alpha05[7,5]=5; alpha05[7,6]=6; alpha05[7,7]=8; alpha05[7,8]=10; alpha05[7,9]=12; alpha05[7,10]=14; alpha05[7,11]=16; alpha05[7,12]=18; alpha05[7,13]=20; alpha05[7,14]=22; alpha05[7,15]=24; alpha05[7,16]=26; alpha05[7,17]=28; alpha05[7,18]=30; alpha05[7,19]=32; alpha05[7,20]=34;
	alpha05[8,3]=2; alpha05[8,4]=4; alpha05[8,5]=6; alpha05[8,6]=8; alpha05[8,7]=10; alpha05[8,8]=13; alpha05[8,9]=15; alpha05[8,10]=17; alpha05[8,11]=19; alpha05[8,12]=22; alpha05[8,13]=24; alpha05[8,14]=26; alpha05[8,15]=29; alpha05[8,16]=31; alpha05[8,17]=34; alpha05[8,18]=36; alpha05[8,19]=38; alpha05[8,20]=41;
	alpha05[9,3]=2; alpha05[9,4]=4; alpha05[9,5]=7; alpha05[9,6]=10; alpha05[9,7]=12; alpha05[9,8]=15; alpha05[9,9]=17; alpha05[9,10]=20; alpha05[9,11]=23; alpha05[9,12]=26; alpha05[9,13]=28; alpha05[9,14]=31; alpha05[9,15]=34; alpha05[9,16]=37; alpha05[9,17]=39; alpha05[9,18]=42; alpha05[9,19]=45; alpha05[9,20]=48;
	alpha05[10,3]=3; alpha05[10,4]=5; alpha05[10,5]=8; alpha05[10,6]=11; alpha05[10,7]=14; alpha05[10,8]=17; alpha05[10,9]=20; alpha05[10,10]=23; alpha05[10,11]=26; alpha05[10,12]=29; alpha05[10,13]=33; alpha05[10,14]=36; alpha05[10,15]=39; alpha05[10,16]=42; alpha05[10,17]=45; alpha05[10,18]=48; alpha05[10,19]=52; alpha05[10,20]=55;
	alpha05[11,3]=3; alpha05[11,4]=6; alpha05[11,5]=9; alpha05[11,6]=13; alpha05[11,7]=16; alpha05[11,8]=19; alpha05[11,9]=23; alpha05[11,10]=26; alpha05[11,11]=30; alpha05[11,12]=33; alpha05[11,13]=37; alpha05[11,14]=40; alpha05[11,15]=44; alpha05[11,16]=47; alpha05[11,17]=51; alpha05[11,18]=55; alpha05[11,19]=58; alpha05[11,20]=62;
	alpha05[12,3]=4; alpha05[12,4]=7; alpha05[12,5]=11; alpha05[12,6]=14; alpha05[12,7]=18; alpha05[12,8]=22; alpha05[12,9]=26; alpha05[12,10]=29; alpha05[12,11]=33; alpha05[12,12]=37; alpha05[12,13]=41; alpha05[12,14]=45; alpha05[12,15]=49; alpha05[12,16]=53; alpha05[12,17]=57; alpha05[12,18]=61; alpha05[12,19]=65; alpha05[12,20]=69;
	alpha05[13,3]=4; alpha05[13,4]=8; alpha05[13,5]=12; alpha05[13,6]=16; alpha05[13,7]=20; alpha05[13,8]=24; alpha05[13,9]=28; alpha05[13,10]=33; alpha05[13,11]=37; alpha05[13,12]=41; alpha05[13,13]=45; alpha05[13,14]=50; alpha05[13,15]=54; alpha05[13,16]=59; alpha05[13,17]=63; alpha05[13,18]=67; alpha05[13,19]=72; alpha05[13,20]=76;
	alpha05[14,3]=5; alpha05[14,4]=9; alpha05[14,5]=13; alpha05[14,6]=17; alpha05[14,7]=22; alpha05[14,8]=26; alpha05[14,9]=31; alpha05[14,10]=36; alpha05[14,11]=40; alpha05[14,12]=45; alpha05[14,13]=50; alpha05[14,14]=55; alpha05[14,15]=59; alpha05[14,16]=64; alpha05[14,17]=67; alpha05[14,18]=74; alpha05[14,19]=78; alpha05[14,20]=83;
	alpha05[15,3]=5; alpha05[15,4]=10; alpha05[15,5]=14; alpha05[15,6]=19; alpha05[15,7]=24; alpha05[15,8]=29; alpha05[15,9]=34; alpha05[15,10]=39; alpha05[15,11]=44; alpha05[15,12]=49; alpha05[15,13]=54; alpha05[15,14]=59; alpha05[15,15]=64; alpha05[15,16]=70; alpha05[15,17]=75; alpha05[15,18]=80; alpha05[15,19]=85; alpha05[15,20]=90;
	alpha05[16,3]=6; alpha05[16,4]=11; alpha05[16,5]=15; alpha05[16,6]=21; alpha05[16,7]=26; alpha05[16,8]=31; alpha05[16,9]=37; alpha05[16,10]=42; alpha05[16,11]=47; alpha05[16,12]=53; alpha05[16,13]=59; alpha05[16,14]=64; alpha05[16,15]=70; alpha05[16,16]=75; alpha05[16,17]=81; alpha05[16,18]=86; alpha05[16,19]=92; alpha05[16,20]=98;
	alpha05[17,3]=6; alpha05[17,4]=11; alpha05[17,5]=17; alpha05[17,6]=22; alpha05[17,7]=28; alpha05[17,8]=34; alpha05[17,9]=39; alpha05[17,10]=45; alpha05[17,11]=51; alpha05[17,12]=57; alpha05[17,13]=63; alpha05[17,14]=67; alpha05[17,15]=75; alpha05[17,16]=81; alpha05[17,17]=87; alpha05[17,18]=93; alpha05[17,19]=99; alpha05[17,20]=105;
	alpha05[18,3]=7; alpha05[18,4]=12; alpha05[18,5]=18; alpha05[18,6]=24; alpha05[18,7]=30; alpha05[18,8]=36; alpha05[18,9]=42; alpha05[18,10]=48; alpha05[18,11]=55; alpha05[18,12]=61; alpha05[18,13]=67; alpha05[18,14]=74; alpha05[18,15]=80; alpha05[18,16]=86; alpha05[18,17]=93; alpha05[18,18]=99; alpha05[18,19]=106; alpha05[18,20]=112;
	alpha05[19,3]=7; alpha05[19,4]=13; alpha05[19,5]=19; alpha05[19,6]=25; alpha05[19,7]=32; alpha05[19,8]=38; alpha05[19,9]=45; alpha05[19,10]=52; alpha05[19,11]=58; alpha05[19,12]=65; alpha05[19,13]=72; alpha05[19,14]=78; alpha05[19,15]=85; alpha05[19,16]=92; alpha05[19,17]=99; alpha05[19,18]=106; alpha05[19,19]=113; alpha05[19,20]=119;
	alpha05[20,3]=8; alpha05[20,4]=14; alpha05[20,5]=20; alpha05[20,6]=27; alpha05[20,7]=34; alpha05[20,8]=41; alpha05[20,9]=48; alpha05[20,10]=55; alpha05[20,11]=62; alpha05[20,12]=69; alpha05[20,13]=76; alpha05[20,14]=83; alpha05[20,15]=90; alpha05[20,16]=98; alpha05[20,17]=105; alpha05[20,18]=112; alpha05[20,19]=119; alpha05[20,20]=127;

	# table for alpha = .01 (99%)
	alpha01[3,3]=0; alpha01[3,4]=0; alpha01[3,5]=0; alpha01[3,6]=0; alpha01[3,7]=0; alpha01[3,8]=0; alpha01[3,9]=0; alpha01[3,10]=0; alpha01[3,11]=0; alpha01[3,12]=1; alpha01[3,13]=1; alpha01[3,14]=1; alpha01[3,15]=2; alpha01[3,16]=2; alpha01[3,17]=2; alpha01[3,18]=2; alpha01[3,19]=3; alpha01[3,20]=3;
	alpha01[4,3]=0; alpha01[4,4]=0; alpha01[4,5]=0; alpha01[4,6]=0; alpha01[4,7]=0; alpha01[4,8]=1; alpha01[4,9]=1; alpha01[4,10]=2; alpha01[4,11]=2; alpha01[4,12]=3; alpha01[4,13]=3; alpha01[4,14]=4; alpha01[4,15]=5; alpha01[4,16]=5; alpha01[4,17]=6; alpha01[4,18]=6; alpha01[4,19]=7; alpha01[4,20]=8;
	alpha01[5,3]=0; alpha01[5,4]=0; alpha01[5,5]=0; alpha01[5,6]=1; alpha01[5,7]=1; alpha01[5,8]=2; alpha01[5,9]=3; alpha01[5,10]=4; alpha01[5,11]=5; alpha01[5,12]=6; alpha01[5,13]=7; alpha01[5,14]=7; alpha01[5,15]=8; alpha01[5,16]=9; alpha01[5,17]=10; alpha01[5,18]=11; alpha01[5,19]=12; alpha01[5,20]=13;
	alpha01[6,3]=0; alpha01[6,4]=0; alpha01[6,5]=1; alpha01[6,6]=2; alpha01[6,7]=3; alpha01[6,8]=4; alpha01[6,9]=5; alpha01[6,10]=6; alpha01[6,11]=7; alpha01[6,12]=9; alpha01[6,13]=10; alpha01[6,14]=11; alpha01[6,15]=12; alpha01[6,16]=13; alpha01[6,17]=15; alpha01[6,18]=16; alpha01[6,19]=17; alpha01[6,20]=18;
	alpha01[7,3]=0; alpha01[7,4]=0; alpha01[7,5]=1; alpha01[7,6]=3; alpha01[7,7]=4; alpha01[7,8]=6; alpha01[7,9]=7; alpha01[7,10]=9; alpha01[7,11]=10; alpha01[7,12]=12; alpha01[7,13]=13; alpha01[7,14]=15; alpha01[7,15]=16; alpha01[7,16]=18; alpha01[7,17]=19; alpha01[7,18]=21; alpha01[7,19]=22; alpha01[7,20]=24;
	alpha01[8,3]=0; alpha01[8,4]=1; alpha01[8,5]=2; alpha01[8,6]=4; alpha01[8,7]=6; alpha01[8,8]=7; alpha01[8,9]=9; alpha01[8,10]=11; alpha01[8,11]=13; alpha01[8,12]=15; alpha01[8,13]=17; alpha01[8,14]=18; alpha01[8,15]=20; alpha01[8,16]=22; alpha01[8,17]=24; alpha01[8,18]=26; alpha01[8,19]=28; alpha01[8,20]=30;
	alpha01[9,3]=0; alpha01[9,4]=1; alpha01[9,5]=3; alpha01[9,6]=5; alpha01[9,7]=7; alpha01[9,8]=9; alpha01[9,9]=11; alpha01[9,10]=13; alpha01[9,11]=16; alpha01[9,12]=18; alpha01[9,13]=20; alpha01[9,14]=22; alpha01[9,15]=24; alpha01[9,16]=27; alpha01[9,17]=29; alpha01[9,18]=31; alpha01[9,19]=33; alpha01[9,20]=36;
	alpha01[10,3]=0; alpha01[10,4]=2; alpha01[10,5]=4; alpha01[10,6]=6; alpha01[10,7]=9; alpha01[10,8]=11; alpha01[10,9]=13; alpha01[10,10]=16; alpha01[10,11]=18; alpha01[10,12]=21; alpha01[10,13]=24; alpha01[10,14]=26; alpha01[10,15]=29; alpha01[10,16]=31; alpha01[10,17]=34; alpha01[10,18]=37; alpha01[10,19]=39; alpha01[10,20]=42;
	alpha01[11,3]=0; alpha01[11,4]=2; alpha01[11,5]=5; alpha01[11,6]=7; alpha01[11,7]=10; alpha01[11,8]=13; alpha01[11,9]=16; alpha01[11,10]=18; alpha01[11,11]=21; alpha01[11,12]=24; alpha01[11,13]=27; alpha01[11,14]=30; alpha01[11,15]=33; alpha01[11,16]=36; alpha01[11,17]=39; alpha01[11,18]=42; alpha01[11,19]=45; alpha01[11,20]=48;
	alpha01[12,3]=1; alpha01[12,4]=3; alpha01[12,5]=6; alpha01[12,6]=9; alpha01[12,7]=12; alpha01[12,8]=15; alpha01[12,9]=18; alpha01[12,10]=21; alpha01[12,11]=24; alpha01[12,12]=27; alpha01[12,13]=31; alpha01[12,14]=34; alpha01[12,15]=37; alpha01[12,16]=41; alpha01[12,17]=44; alpha01[12,18]=47; alpha01[12,19]=51; alpha01[12,20]=54;
	alpha01[13,3]=1; alpha01[13,4]=3; alpha01[13,5]=7; alpha01[13,6]=10; alpha01[13,7]=13; alpha01[13,8]=17; alpha01[13,9]=20; alpha01[13,10]=24; alpha01[13,11]=27; alpha01[13,12]=31; alpha01[13,13]=34; alpha01[13,14]=38; alpha01[13,15]=42; alpha01[13,16]=45; alpha01[13,17]=49; alpha01[13,18]=53; alpha01[13,19]=56; alpha01[13,20]=60;
	alpha01[14,3]=1; alpha01[14,4]=4; alpha01[14,5]=7; alpha01[14,6]=11; alpha01[14,7]=15; alpha01[14,8]=18; alpha01[14,9]=22; alpha01[14,10]=26; alpha01[14,11]=30; alpha01[14,12]=34; alpha01[14,13]=38; alpha01[14,14]=42; alpha01[14,15]=46; alpha01[14,16]=50; alpha01[14,17]=54; alpha01[14,18]=58; alpha01[14,19]=63; alpha01[14,20]=67;
	alpha01[15,3]=2; alpha01[15,4]=5; alpha01[15,5]=8; alpha01[15,6]=12; alpha01[15,7]=16; alpha01[15,8]=20; alpha01[15,9]=24; alpha01[15,10]=29; alpha01[15,11]=33; alpha01[15,12]=37; alpha01[15,13]=42; alpha01[15,14]=46; alpha01[15,15]=51; alpha01[15,16]=55; alpha01[15,17]=60; alpha01[15,18]=64; alpha01[15,19]=69; alpha01[15,20]=73;
	alpha01[16,3]=2; alpha01[16,4]=5; alpha01[16,5]=9; alpha01[16,6]=13; alpha01[16,7]=18; alpha01[16,8]=22; alpha01[16,9]=27; alpha01[16,10]=31; alpha01[16,11]=36; alpha01[16,12]=41; alpha01[16,13]=45; alpha01[16,14]=50; alpha01[16,15]=55; alpha01[16,16]=60; alpha01[16,17]=65; alpha01[16,18]=70; alpha01[16,19]=74; alpha01[16,20]=79;
	alpha01[17,3]=2; alpha01[17,4]=6; alpha01[17,5]=10; alpha01[17,6]=15; alpha01[17,7]=19; alpha01[17,8]=24; alpha01[17,9]=29; alpha01[17,10]=34; alpha01[17,11]=39; alpha01[17,12]=44; alpha01[17,13]=49; alpha01[17,14]=54; alpha01[17,15]=60; alpha01[17,16]=65; alpha01[17,17]=70; alpha01[17,18]=75; alpha01[17,19]=81; alpha01[17,20]=86;
	alpha01[18,3]=2; alpha01[18,4]=6; alpha01[18,5]=11; alpha01[18,6]=16; alpha01[18,7]=21; alpha01[18,8]=26; alpha01[18,9]=31; alpha01[18,10]=37; alpha01[18,11]=42; alpha01[18,12]=47; alpha01[18,13]=53; alpha01[18,14]=58; alpha01[18,15]=64; alpha01[18,16]=70; alpha01[18,17]=75; alpha01[18,18]=81; alpha01[18,19]=87; alpha01[18,20]=92;
	alpha01[19,3]=3; alpha01[19,4]=7; alpha01[19,5]=12; alpha01[19,6]=17; alpha01[19,7]=22; alpha01[19,8]=28; alpha01[19,9]=33; alpha01[19,10]=39; alpha01[19,11]=45; alpha01[19,12]=51; alpha01[19,13]=56; alpha01[19,14]=63; alpha01[19,15]=69; alpha01[19,16]=74; alpha01[19,17]=81; alpha01[19,18]=87; alpha01[19,19]=93; alpha01[19,20]=99;
	alpha01[20,3]=3; alpha01[20,4]=8; alpha01[20,5]=13; alpha01[20,6]=18; alpha01[20,7]=24; alpha01[20,8]=30; alpha01[20,9]=36; alpha01[20,10]=42; alpha01[20,11]=48; alpha01[20,12]=54; alpha01[20,13]=60; alpha01[20,14]=67; alpha01[20,15]=73; alpha01[20,16]=79; alpha01[20,17]=86; alpha01[20,18]=92; alpha01[20,19]=99; alpha01[20,20]=105;
}

# Determine if the specified layer is a raster layer
func isRasterLayer(class GRE_LAYER l)
{
	return (l.Type == "Raster");
}

# Update a record in the database table given the recordNum, fieldName, and value to write
func updateRecord(class Vector V, string tableType, string tableName, numeric recordNum, string fieldname, numeric value)
{
	if(tableType=="point")
	{
		V.point.(tableName)[@recordNum].(fieldname) = value;
		return 1;
	}
	else if(tableType=="line")
	{
		V.line.(tableName)[@recordNum].(fieldname) = value;
		return 1;
	}
	else if(tableType=="poly")
	{
		V.line.(tableName)[@recordNum].(fieldname) = value;
		return 1;
	}
	else return 0;
}

# Write raster statistics to the database table
proc writeStatisticsToTable(numeric recordNum, string rastNameStr, numeric u, numeric z, numeric sig)
{
	local class string rastName = rastNameStr;
	rastName = rastName.slice(0,11);
	updateRecord(pointVector, "point", "ResultTable", recordNum, rastName + "_U", u);
	updateRecord(pointVector, "point", "ResultTable", recordNum, rastName + "_Z", z);
	updateRecord(pointVector, "point", "ResultTable", recordNum, rastName + "_sig", sig);
}

# Write a new record and attach it to the element specified by 'pointNum'
func writePointRecord(numeric pointNum, numeric length, numeric width)
{
	local array numeric records[1];
	records[1] = TableWriteRecord(pointTable, 0, pointNum, length, width);

	TableWriteAttachment(pointTable, pointNum, records, 1, "point");

	return records[1];	# the newly created record number
}

# Write a new record and attach it to the element specified by 'polyNum'
proc writePolyRecord(numeric length, numeric width)
{
	local array numeric records[1];
	records[1] = TableWriteRecord(polyTable, 0, length, width);

	local numeric polyNum;
	for (polyNum=1; polyNum<=NumVectorPolys(polyVector); polyNum++)
	{
		TableWriteAttachment(polyTable, polyNum, records, 1, "polygon");
	}
}

# Determine if the computed value is statistically significant or not
# return 1 if significant, 0 otherwise
func computeSignificance(numeric z, numeric u)
{
	if (n2 <= 20)
	{
		if (n1==0 && n2==0) return 0;
		if (n1==0 || n2==0) return 1;
		local numeric criticalU=0;
		if (ALPHA == .05)
		{
			criticalU = alpha05[n2,n1];
		}
		else if (ALPHA == .01)
		{
			criticalU = alpha01[n2,n1];
		}
		else
		{
			PopupMessage("Insufficient information to perform significance test");
		}
		if (u > criticalU) return 1;
		return 0;
	}
	else
	{
		if (ALPHA == .05)
		{
			return (z > 1.96);
		}
		else if (ALPHA == .01)
		{
			return (z > 2.575);
		}
		else
		{
			PopupMessage("Insufficient information to perform significance test");
		}
	}

}

# Calculate Z based on the U value
# For large samples the normal approximation z = (U - mU)/oU can be used where
# mU and oU are the mean and standard deviation of U as given by:
# mU = n1n2/2 and oU = sqrt(n1n2(n1+n2+1)/12)
func calculateZScore(numeric U, numeric n1, numeric n2)
{
	local numeric mU = n1*n2/2;
	local numeric oU = sqrt(n1*n2*(n1+n2+1)/12);

	return abs((U - mU)/oU);
}

# Get minimum of two numbers
func min(numeric a, numeric b)
{
	if (a 0)
	{
		# for each of the h sets of elements
		for i = h-1 to last
		{
			local numeric key = mergedArray[i];
			local numeric bkey = bitset[i];
			local numeric j = i;

			while (j>=h && mergedArray[j-h] > key)
			{
				mergedArray[j] = mergedArray[j-h];
				bitset[j] = bitset[j-h];
				j = j - h;
			}
			mergedArray[j] = key;
			bitset[j] = bkey;
		}
		h = floor(h/3);
	}

	# Generate ranks
	local numeric next;
	for i=1 to last-1
	{
		next = i;
		# look for ties in set and resolve all at once
		local numeric sum=rank[next], count=1;
		while(next 0)
	{
		lineNumber = FindClosestLine(v, srcPoint.x, srcPoint.y, georef, snapDistance);
	}
	else
	{
		PopupMessage("Selected vector does not have any lines");
	}

	if (lineNumber==0) 	# check for error in finding line
	{
		PopupMessage("Cannot snap the specified point to line given existing snap distance");
	}
	return lineNumber;
}

# Takes user selected point and finds a point on the nearest line to snap to
func class POINT2D snapToLine(class POINT2D srcPoint, numeric snapDistance)
{
	local class POINT2D retPoint, tmpPoint;

	local numeric lineNum = getClosestLine(lineVector, srcPoint, snapDistance);
	if (lineNum==0) 	# check for error in finding line
	{
		PopupMessage("Cannot snap the specified point to line given set snap distance");
	}
	else	# no error so find the closest point to snap to
	{
		local class POLYLINE polyline = GetVectorLine(lineVector, lineNum);
		if (polyline == 0)
		{
			PopupMessage("Cannot snap the specified point to line given set snap distance");
		}
		else
		{
			local class Georef georef = GetLastUsedGeorefObject(lineVector);
			tmpPoint = 	MapToObject(georef, srcPoint.x, srcPoint.y, lineVector);
			retPoint = polyline.FindClosestPoint(tmpPoint);
			retPoint = ObjectToMap(lineVector, retPoint.x, retPoint.y, georef);
		}
	}
	return retPoint;
}

# compute the slope between two points (for defining the rectangle)
func computeSlope(class POINT2D point1, class POINT2D point2)
{
	if (point2.x==point1.x) return infinity;
	return (point2.y - point1.y) / (point2.x - point1.x);
}

# create the rectangle as specified by the corner points
proc addRectangle(class Vector destVector, class POINT2D ll, class POINT2D ul, class POINT2D ur, class POINT2D lr)
{
	local array numeric x[5];
	local array numeric y[5];

	x[1] = ll.x;
	y[1] = ll.y;
	x[2] = ul.x;
	y[2] = ul.y;
	x[3] = ur.x;
	y[3] = ur.y;
	x[4] = lr.x;
	y[4] = lr.y;
	x[5] = ll.x;
	y[5] = ll.y;

	VectorAddLine(destVector, 5, x, y);
#	refreshVector();
}

# Compute the slope of the polyline near the centerpoint
func computeLineSlope(class Vector destVector, class POINT2D centerPoint, numeric lineNum)
{
	# Get the line as a polyline
	local class POLYLINE polyline = GetVectorLine(lineVector, lineNum);

	# Set up the vertices for slope computation (first, last, selected)
	local class Georef georef = GetLastUsedGeorefObject(lineVector);
	local class POINT2D objCenterPoint = MapToObject(georef, centerPoint.x, centerPoint.y, lineVector);
	local numeric vertexNum = polyline.FindClosestVertex(objCenterPoint);
	local numeric first = 0, last = polyline.GetNumPoints() - 1;

	# set up vertices for computation
	if (vertexNum == first) # if vertex is first in line use first two vertices 
	{
		last = first + 1;
	}
	else if (vertexNum == last) # if vertex is last in line use last two vertices 
	{
		first = last - 1;
	}
	else # vertex isn't the first or last, use adjacent vertices for computation
	{
		first = vertexNum - 1;
		last = vertexNum + 1;
	}

	# Get the vertices and convert to map coords
	local class POINT2D pointFirst, pointLast;
	pointFirst = polyline.GetVertex(first);
	pointFirst = ObjectToMap(lineVector, pointFirst.x, pointFirst.y, georef);
	pointLast = polyline.GetVertex(last);
	pointLast = ObjectToMap(lineVector, pointLast.x, pointLast.y, georef);

	# compute the slope
	return computeSlope(pointFirst, pointLast);
}

# Creates a rectangle poly in 'destVector' with the slope of the line at linenum.
# The rectangle is centered at 'centerPoint' with dimensions length x width.
proc createRectangle(class Vector destVector, numeric length, numeric width, class POINT2D centerPoint, numeric lineNum)
{
	local numeric slope = computeLineSlope(destVector, centerPoint, lineNum);

	# handle the orientation (slope) of the rectangle about the point
	local class POINT2D tmp, ul, ur, ll, lr;
	numeric theta = atand(slope);

	tmp.x = centerPoint.x - .5*width*cosd(theta);
	tmp.y = centerPoint.y - .5*width*sind(theta);

	# get lower left
	ll.x = tmp.x + .5*length*cosd(90 - theta);
	ll.y = tmp.y - .5*length*sind(90 - theta);

	# get upper left
	ul.x = tmp.x - .5*length*cosd(90 - theta);
	ul.y = tmp.y + .5*length*sind(90 - theta);

	tmp.x = centerPoint.x + .5*width*cosd(theta);
	tmp.y = centerPoint.y + .5*width*sind(theta);

	# get lower right
	lr.x = tmp.x + .5*length*cosd(90 - theta);
	lr.y = tmp.y - .5*length*sind(90 - theta);

	# get upper right
	ur.x = tmp.x - .5*length*cosd(90 - theta);
	ur.y = tmp.y + .5*length*sind(90 - theta);


	addRectangle(destVector, ll, ul, ur, lr);
}

# create the line given adding it to the destVector
proc createLine(class Vector destVector, class POLYLINE line)
{
	numeric numPoints = line.GetNumPoints();
	local array numeric xcoords[numPoints];
	local array numeric ycoords[numPoints];

	local class POINT2D vertex;
	local class Georef georef = GetLastUsedGeorefObject(lineVector);

	local numeric i, x, y;
	for (i=1; i<=numPoints; i++)
	{
		vertex = line.GetVertex(i-1);
		ObjectToMap(lineVector, vertex.x, vertex.y, georef, x, y);
		xcoords[i] = x;
		ycoords[i] = y;
	}

# bug in scope?  this is cleared to 0
numPoints = line.GetNumPoints();
	VectorAddLine(destVector, numPoints, xcoords, ycoords);
}

# Get the snap distance setting
func getSnapDistance()
{
	local class GUI_CTRL_EDIT_NUMBER snapCtrl = dlgwin.GetCtrlByID("snap");
	return snapCtrl.GetValue();
}

# Called when user presses 'left' pointer/mouse button. 
func OnLeftButtonPress()
{ 
	# If the selected layer is not valid, don't do anything.
	if (checkLayer())
	{
		# Set local variables
		local class POINT2D point;

		# Check point.
		point.x = PointerX;
		point.y = PointerY;

		point = TransPoint2D(point, ViewGetTransViewToScreen(View, 1));
		point = TransPoint2D(point, ViewGetTransMapToView(View, vectorLayer.Projection, 1));
		local numeric snapDistance = getSnapDistance();
		point = snapToLine(point, snapDistance);

		# Add the point to the target vector
		if (point.x !=0 && point.y !=0)
		{
			VectorAddPoint(pointVector, point.x, point.y);
#			pointLayer = activegroup.GetLayerByName(pointLayerName);
#			if (pointLayer==0) PopupMessage("null point layer "+ pointLayerName);
#			else pointLayer.UpdateExtents();
			View.Redraw(0);	# if using 7.0 only redraw point and poly layers
		}
	}
}

# Creates the vector that will store the resultant points
proc createDestVector(class Vector destVector)
{
	local string flags$ = "Polygonal";
	GetOutputVector(destVector, flags$);
	local class Georef georef = GetLastUsedGeorefObject(lineVector);
	if (georef==0) PopupMessage("No georef");

	# Create Implied georeference for output vector based on lineVector's projection
	else
	{
		DeleteGeoref(destVector);
		CreateImpliedGeoref(destVector, georef.Projection);
	}
	VectorToolkitInit(destVector);
}

# Creates the vector that will store the resultant points
proc createTmpDestVector(class Vector destVector)
{
	local string flags$ = "Polygonal";
	CreateTempVector(destVector, flags$);
	local class Georef georef = GetLastUsedGeorefObject(lineVector);
	if (georef==0) PopupMessage("No georef");

	# Create Implied georeference for output vector based on lineVector's projection
	else
	{
		DeleteGeoref(destVector);
		CreateImpliedGeoref(destVector, georef.Projection);
	}
	VectorToolkitInit(destVector);
}

# Called after test is run - new vector must then be used
proc ClosePolyVector()
{
	CloseVector(polyVector);
	CloseVector(tmpVector);

	polyCtrl.SetValueStr("");
}

# Set the alpha value based on the dialog's settings
proc setAlphaValue()
{
	local class GUI_FORM_RADIOGROUP alphaRadio = dlgwin.GetCtrlByID("alpha");
	if (alphaRadio.GetSelected()=="alpha01") ALPHA = .01;
	else ALPHA = .05;
}

# Utility function to bound val between two limits
func bound(numeric val, numeric lowerLimit, numeric upperLimit)
{
	if (val < lowerLimit) return lowerLimit;
	if (val > upperLimit) return upperLimit;
	return val;
}

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

# Function used to split the polyline at the edges of the rectangle
func class POLYLINE splitPolyline(class Vector destVector, class POINT2D centerPoint, numeric width, class POLYLINE polyline, numeric lineNum)
{
	local numeric slope = computeLineSlope(destVector, centerPoint, lineNum);

	# handle the orientation (slope) of the rectangle about the point
	local class POINT2D left, right;
	numeric theta = atand(slope);

	# Get the georef so we can work in obj coords as polyline does
	local class Georef georef = GetLastUsedGeorefObject(lineVector);

	# find the left edge (not necessary left edge of rect)
	left.x = centerPoint.x - .5*width*cosd(theta);
	left.y = centerPoint.y - .5*width*sind(theta);
	local class POINT2D objLeftPoint = MapToObject(georef, left.x, left.y, lineVector);
	local numeric leftNum = polyline.FindClosestVertex(objLeftPoint);

	# find the right edge (not necessary right edge of rect)
	right.x = centerPoint.x + .5*width*cosd(theta);
	right.y = centerPoint.y + .5*width*sind(theta);
	local class POINT2D objRightPoint = MapToObject(georef, right.x, right.y, lineVector);
	local numeric rightNum = polyline.FindClosestVertex(objRightPoint);
	# swap if necessary
	if (leftNum>rightNum)
	{
		local numeric tmp = leftNum;
		leftNum = rightNum;
		rightNum = tmp;
	}

	# calculate necessary numpoints compensating for curvature
	local numeric numpoints;
	numpoints = 2 * width * polyline.GetNumPoints() / polyline.ComputeLength();

	# pad vertices past the edge
	local numeric pad = (numpoints - (rightNum - leftNum));
	if (pad<25) pad = 25; # use at least 25
	leftNum = leftNum - pad;
	rightNum = rightNum + pad;

	leftNum = bound(leftNum, 0, polyline.GetNumPoints()-1);
	rightNum = bound(rightNum, 0, polyline.GetNumPoints()-1);

	# create the polyline
	local class POLYLINE retLine;
	local numeric v=0;
	for (v=leftNum; v<=rightNum; v++)
	{
		retLine.AppendVertex(polyline.GetVertex(v));
	}

	return retLine;
}

# Get the Y scale for the current field
func getYScale(string field)
{
	if (field == "U_Value") return .5;		# max is 'max'
	else if (field == "z_score") return 25;	# max is 4 (100 scaled)
	return 50;							# max is 1	(50 scaled)
}

# Style the points by script
func string generateStyleScript(string field)
{
	local class STRINGLIST rasterLayerList, rasterFieldList;

	# loop over each raster and perform calculations
	local class GRE_LAYER currentRaster = activegroup.FirstLayer;
	while (currentRaster != 0)
	{
		if (isRasterLayer(currentRaster))
		{
			DispGetRasterFromLayer(rast, currentRaster);

			local class string name, suffix;
			if (field == "U_Value") suffix = "_U";
			else if (field == "z_score") suffix = "_Z";
			else suffix = "_sig";
			name = rast.$INFO.Name;
			rasterLayerList.AddToEnd(name);
			name = name.slice(0,11) + suffix;
			rasterFieldList.AddToEnd(name);

		}
		currentRaster = currentRaster.NextLayer;
	}

	local class string script ='
	# default colors to use for styles
	local class COLOR color;
	class STRINGLIST colors;
	colors.AddToEnd("red");
	colors.AddToEnd("green");
	colors.AddToEnd("blue");
	colors.AddToEnd("cyan");
	colors.AddToEnd("magenta");
	colors.AddToEnd("yellow");

	class STRINGLIST rasters;
	';
	local numeric r, numRasts = rasterLayerList.GetNumItems();
	for (r=0; r0) {currentRun++;}
			LayerOpenControls(pointLayer);
		}
	}
}

func OnOk()
{
	OnApply();
	return 1;
}

# Callback for when the active group changes.
proc cbGroup()
{
	activegroup = Layout.ActiveGroup;
}

# Called when tool is activated.
# If the tool implements a dialog it should be "managed" (displayed) here.
proc OnActivate ()
{
	dlgwin.SetOkEnabled(0);
	dlgwin.Open();
}


# Called when tool is deactivated (usually when switching to another tool).
# If the tool implements a dialog it should be "unmanaged" (hidden) here.
proc OnDeActivate ()
{
	dlgwin.Close(0);
#	View.SetDefaultTool();
}

# Create the desired fields in the point vector table
proc createPointTableFields()
{
	TableAddFieldInteger(pointTable, "ID");
	TableAddFieldInteger(pointTable, "length");
	TableAddFieldInteger(pointTable, "width");
}

# Create the vector point database tables as desired
proc initializePointDatabaseTable(class Vector v)
{
	local string name$ = "ResultTable";
	local string desc$ = "Computed statistics for U-value, z-value, and significance";
	local class DATABASE db = OpenVectorPointDatabase(v);

	# if the table doesn't exist it needs to be created
	if(!TableExists(db, name$))
	{
		pointTable = TableCreate(db, name$, desc$);
		pointTable.OneElementPerRecord = 1;
		createPointTableFields();
	}
	# else the table does exist, get info for it
	else
	{
		pointTable = DatabaseGetTableInfo(db, name$);
	}
}

# Create the desired fields in the polygon vector table
proc createPolygonTableFields()
{
	TableAddFieldInteger(polyTable, "Length");
	TableAddFieldInteger(polyTable, "Width");
}

# Create the vector point database tables as desired
proc initializePolygonDatabaseTable(class Vector v)
{
	local string name$ = "Boundary";
	local string desc$ = "Boundary size used for U-Value computation";
	local class DATABASE db = OpenVectorPolyDatabase(v);

	# if the table doesn't exist it needs to be created
	if(!TableExists(db, name$))
	{
		polyTable = TableCreate(db, name$, desc$);
		polyTable.OneRecordPerElement = 1;
		createPolygonTableFields();
	}
	# else the table does exist, get info for it
	else
	{
		polyTable = DatabaseGetTableInfo(db, name$);
	}
}

# Procedure called when user presses the button to add new point vector object
proc GetPointVector()
{
	if (checkLayer()) 
	{
		createDestVector(pointVector);
		initializePointDatabaseTable(pointVector);
	}
	local class FILEPATH fp = pointVector.$INFO.Filename;
	pointCtrl.SetValueStr(fp.GetName() +" / "+ pointVector.$INFO.Name);
}

# Procedure called when user presses the button to add new polygon vector object
proc GetPolyVector()
{
	createDestVector(polyVector);
	initializePolygonDatabaseTable(polyVector);
	createTmpDestVector(tmpVector);

	local class FILEPATH fp = polyVector.$INFO.Filename;
	polyCtrl.SetValueStr(fp.GetName() +" / "+ polyVector.$INFO.Name);
}

# Called the first time the tool is activated.
proc OnInitialize ()
{
	initCriticalValuesTables();

	if (Layout) {
		WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup);
		activegroup = Layout.ActiveGroup;
		}
	else activegroup = Group;

	local string dialogSpecXml$ = '
	
	
		
			
				
					
						
						
					
					
						
						
					
				
				
					
						
						
						
					
					
						
						
						
					
					
						
						
						
					
				
				
					
						
						
					
				
				
					
						
						
						
					
				
			
		
	
	';

	# Parse the xml dialog specification
	local class XMLDOC dlgdoc;
	local numeric err = dlgdoc.Parse(dialogSpecXml$);
	if (err < 0) {
		PopupError(err);
		Exit();
		}
	local string dlgid$ = "utestdialog";
	local class XMLNODE dlgnode = dlgdoc.GetElementByID(dlgid$);
	if (dlgnode == 0) {
		PopupMessage("Could not find specifed id: "+dlgid$);
		Exit();
		}
	dlgwin.SetXMLNode(dlgnode);
	dlgwin.CreateModeless(View.InfoForm);

	pointCtrl = dlgwin.GetCtrlByID("point");
	polyCtrl = dlgwin.GetCtrlByID("poly");

	widthCtrl = dlgwin.GetCtrlByID("width");
	lengthCtrl = dlgwin.GetCtrlByID("length");
}

proc OnClose()
	{
	dlgwin.Close(1);
	View.SetDefaultTool();		# switch to default tool on the View tool bar
	}


 


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