Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
### NETWORK1.SML
### script to use network analysis on a road network (lines in vector Roads)
### to find short route between farm gates (points in vector Farms) and
### processing plants (points in vector Plants). Farm gate and plant points do
### not fall exactly on road lines. Input vectors for Roads and Farms are copied to
### a selected output file for modification.
### For each farm gate point, the script adds a node at the closest point on the
### closest road line and keeps track of these nodes in an array that associates
### them with the correct farm. A new table for nodes in the Road vector also
### records the farm number for each added nodes Nodes are similarly added and
### attributed for each of the processing plants.
### The shortest distance between each farm and processing plant is then
### calculated using network analysis functions. The script adds two
### new tables to the point database of the Farms vector: one with records
### attached to each point that list the distance to each of the processing plants
### and another that provides the geographic coordinates of each processing plant
### in the same coordinate system used by the Farms object.
### Updated 8 March 2006 - DRB
### -Now handles case where Farm and Plant share the same node in the roads vector
### Variable Declarations
vector FarmsIn, Plants, RoadsIn;
vector Farms, Roads;
class GEOREF farmgeo, tempgeo, plantgeo;
numeric numPoints;
numeric numFarms;
numeric numPlants;
numeric numLines;
numeric i, j; # counters for processing loops
numeric tempx; # x coordinate of farm gate or processing plant
numeric tempy; # y coordinate of farm gate or processing plant
numeric linenumber; # element number for line closest to current point
numeric a, b; # map coordinates of closest point on closest line
numeric distance;
class DATABASE db; # handle for Farms point database
class DBTABLEINFO tinfo1, tinfo2; # handles for new tables in Farms point database
class DATABASE dblines; # handle for road lines database
class DATABASE dbnodes; # handle for road node database
class DBTABLEINFO nftable, nptable; # handles for new tables in road node database
######## Program ########
clear(); # clear console
############################################################
### Get input vector objects and the filename for output file
############################################################
GetInputVector( FarmsIn );
GetInputVector( Plants );
GetInputVector( RoadsIn );
### check for LINESTATS table in Roads line database and
### if not present create prompt user to create one and exit.
dblines = OpenVectorLineDatabase( RoadsIn );
if ( !TableExists(dblines, "LINESTATS" ) ) {
PopupMessage("Missing LINESTATS table. \nCompute Standard Attributes for Roads vector before running script." );
Exit();
}
### copy FarmsIn to output file and open copy Farms initialized for modification
### with VectorToolkit
string srcfilename$, destfilename$, objName$;
numeric srcObjectNum;
destfilename$ = GetOutputFileName("", "Select an output Project File:", "rvc");
CreateProjectFile(destfilename$, "output from network1.sml");
srcfilename$ = GetObjectFileName( FarmsIn );
srcObjectNum = GetObjectNumber( FarmsIn );
objName$ = GetObjectName( srcfilename$, srcObjectNum );
CopyObject( srcfilename$, srcObjectNum, destfilename$ );
OpenVector( Farms, destfilename$, objName$, "VectorToolkit" );
CloseVector( FarmsIn );
### copy RoadsIn to output file and open copy Roads initialized for modification
### with VectorToolkit
srcfilename$ = GetObjectFileName( RoadsIn );
srcObjectNum = GetObjectNumber( RoadsIn );
objName$ = GetObjectName( srcfilename$, srcObjectNum );
CopyObject( srcfilename$, srcObjectNum, destfilename$ );
OpenVector( Roads, destfilename$, objName$, "VectorToolkit" );
CloseVector( RoadsIn );
### get georeference information for each vector
farmgeo = GetLastUsedGeorefObject( Farms );
tempgeo = GetLastUsedGeorefObject( Roads );
plantgeo = GetLastUsedGeorefObject( Plants );
#########################################################
### create new point database tables in Farms vector
#########################################################
### create new table to hold processing plant locations
db = OpenVectorPointDatabase(Farms);
numeric recordnumber;
Array numeric records[1];
tinfo1 = TableCreate(db,"Plant_Num","Created by SML script");
TableAddFieldInteger( tinfo1, "Plant", 3 );
TableAddFieldFloat( tinfo1, "xcoord", 25, 6 );
TableAddFieldFloat( tinfo1, "ycoord", 25, 6 );
### create new table to hold distance to each processing plant
string tablename$ = "Plant_Dist";
tinfo2 = TableCreate( db, tablename$, "Created by SML Script" );
TableAddFieldInteger( tinfo2, "Plant", 3 );
class DBFIELDINFO the_field;
the_field = TableAddFieldFloat( tinfo2, "Net_Dist", 25, 6 );
the_field.UnitType = "Distance";
the_field.Units = "kilometers";
#########################################################
### create new node database tables in Roads vector
#########################################################
dbnodes = OpenVectorNodeDatabase( Roads );
### create new table to hold Farm number for new farm gate nodes
nftable = TableCreate( dbnodes, "FarmGates", "Farm gate node info" );
TableAddFieldInteger( nftable, "FarmNum", 7 );
### create new table to hold Plant number for plant nodes
nptable = TableCreate( dbnodes, "Plants", "Plant info" );
TableAddFieldInteger( nptable, "PlantNum", 9 );
##########################################################
### process Farm points and add nodes to lines
##########################################################
numFarms = NumVectorPoints( Farms );
printf( "The number of farms is %d\n", numFarms );
Array numeric farms[numFarms]; # array to hold node number for each farm gate;
# array index = element number of farm gate point
for i = 1 to numFarms {
SetStatusMessage( sprintf( "Processing point %d of %d of farms",i,numFarms ) );
### get object coordinate of farm gate point and transform to map coordinates
tempx = Farms.point[i].Internal.x;
tempy = Farms.point[i].Internal.y;
GeorefTrans( farmgeo, tempx, tempy, tempgeo, tempx, tempy );
### find line closest to point and closest point on that line and add node
linenumber = FindClosestLine( Roads, tempx, tempy );
ClosestPointOnLine( Roads, linenumber, tempx, tempy, a, b );
VectorAddNode( Roads, a, b, 1 );
### update farm gate array
farms[i] = FindClosestNode( Roads, a, b );
### add record to FarmGates node table in Roads vector
recordnumber = TableNewRecord( nftable, i );
records[1] = recordnumber;
TableWriteAttachment( nftable, farms[i], records, 1 );
}
#######################################################
### process plant points and add nodes to lines
#######################################################
numPlants = NumVectorPoints( Plants );
printf( "The number of plants is %d\n",numPlants );
Array numeric plants[numPlants]; # array to hold node number for each processing plant;
for i = 1 to numPlants {
SetStatusMessage( sprintf( "Processing point %d of %d of plants", i, numPlants ) );
### get object coordinate of processing plant point and transform to map coordinates
tempx = Plants.point[i].Internal.x;
tempy = Plants.point[i].Internal.y;
GeorefTrans( plantgeo, tempx, tempy, tempgeo, tempx, tempy );
### find line closest to point and closest point on that line and add node
linenumber = FindClosestLine( Roads, tempx, tempy );
ClosestPointOnLine( Roads, linenumber, tempx, tempy, a, b );
VectorAddNode( Roads, a, b, 1 );
### update processing plant array
plants[i] = FindClosestNode( Roads, a, b );
### add record to table Plant_Num table in Farms vector
recordnumber = TableNewRecord( tinfo1, i, tempx, tempy );
### add record to Plants node table in Roads vector
recordnumber = TableNewRecord( nptable, i );
records[1] = recordnumber;
TableWriteAttachment( nptable, plants[i], records, 1 );
}
#VectorValidate( Roads );
VectorUpdateStdAttributes( Roads );
CloseVector( Roads ); # close road vector
#########################################################
### perform network analysis on road vector
#########################################################
class Network net;
class Route route;
class MultiRoute multiroute;
numeric imp; # impedance for road line = line length
string report$; # string for network route report
### initialize vector for network analysis
string filename$ = GetObjectFileName( Roads );
net = NetworkInit( filename$, GetObjectName( filename$, GetObjectNumber( Roads ) ) );
NetworkSetDefaultAttributes( net );
### process road lines to set impedance in each direction from line length
numLines = NumVectorLines( Roads );
for i = 1 to numLines {
imp = ( Roads.line[i].LINESTATS.Length );
NetworkLineSetImpedance( net, i, imp, "FromTo" );
NetworkLineSetImpedance( net, i, imp, "ToFrom" );
}
### perform multiroute analysis
numeric total = numFarms * numPlants;
numeric count = 1;
for j = 1 to numPlants {
printf( "Plant %d\n", j );
SetStatusMessage( sprintf( "Calculating all routes from plant %d of %d", j, numPlants ) );
NetworkCalculateMultiRoute( net, plants[j], farms, numFarms, multiroute );
for i = 1 to numFarms {
SetStatusMessage( sprintf( "Calculating route %d of %d", count, total ) );
count += 1;
if (plants[j] == farms[i]) {
printf( "Plant %d is at the same location as farm %d\n", j, i);
### set distance to 0 and update plant distance table in Farms vector
recordnumber = TableNewRecord( tinfo2, j, 0 );
records[1] = recordnumber;
TableWriteAttachment( tinfo2, i, records, 1 );
} else {
printf( "Route from plant %d to farm %d\n", j, i );
NetworkMultiRouteGetRoute( multiroute, farms[i], route );
report$ = NetworkRouteGetReport( route );
### get distance and update plant distance table in Farms vector
distance = StrToNum( GetToken( report$, " ", 18 ) );
recordnumber = TableNewRecord( tinfo2, j, distance / 1000 ); # m / 1000 = km
records[1] = recordnumber;
TableWriteAttachment( tinfo2, i, records, 1 );
NetworkRouteClose( route );
}
}
NetworkMultiRouteClose(multiroute);
}
NetworkClose(net);
CloseVector( Farms );
CloseVector( Roads );
CloseVector( Plants );
printf("Script Ran to Completion");