doqq7.sml

  Download

More scripts: Advanced

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
# doqq7.sml
#
#
##############################################################################
# global variables that need declaring
##############################################################################
class TEXTSTYLE textstyle, labelstyle;
class GRE_GROUP group, mapgroup, indexgroup;
class GRE_LAYER_RASTER rastlayer;
class GRE_LAYER_VECTOR vectlayer;
class GRE_LAYER_MAPGRID gridlayer, neatlayer;
class GRE_LAYER_TEXT textlayer;
class GRE_LAYER layer;
class RECT extents;		# Extents of DOQQ in lat/lon
# for step 0
class OBJECTINFO layoutObject;
raster DOQQ;
vector WetlandsVector;
string layoutFileName$, layoutObjectName$;
string doqqFileName$, doqqObjectName$, doqqObjectDesc$, templateDir$;
numeric layoutObjectNumber, doqqObjectNumber;
# for steps 1-3
class FILE inFile;
string workDir$, name$, prffile$, currentDate$, inFile$, ccs755$;
string  newname$, oldname$, objname$;
numeric numLines;
# for step 4
class DATABASE db;
class DBTABLEINFO table;
numeric photodate, dftcont, dftbright, wantNeatLine, ntokens, contrast, brightness;
string photodate$, quadname$, reqfilen$, direct$, a$, imgdate$, maptitle$;
class XmSeparator sep;
class XmForm br;
# for step 5-10
class GRE_LAYOUT layout;
class DBTABLEINFO tinfo;
# for step 11
class Georef georef;
numeric xmin, ymin, xmax, ymax;
numeric halfsize, twosec, cx, cy;
##############################################################################
# initialize global variables
##############################################################################
# This is the map projection we will use everywhere
class MAPPROJ projection;
projection.System = "United States State Plane 1983";
projection.Zone = "Maryland";
# This is the projection used for clipping
class MAPPROJ latlon;
latlon.System = "Latitude / Longitude";
latlon.Datum = "North American 1983";
latlon.Ellipsoid = "GRS 1980";
#=============================================================================
clear();
##############################################################################
# function to count number of lines in a text file
##############################################################################
func CountLines(string fileName$) {
	class file f;
	numeric c;
	string line$;
	f = fopen(fileName$, "r");
	c = 0;
	line$ = fgetline$(f);
	while (line$ != "" ) {
		c = c + 1;
		line$ = fgetline$(f);
		}
	fclose(f);
	return(c);
	}
##############################################################################
# step 0: 
# Prompt for Input objects
############################################################################## 
layoutFileName$ = IniReadString("DOQQSML", "Layout");
layoutObject = SelectInputObject("D2DWIN", "Select the template layout", layoutFileName$);
layoutFileName$ = layoutObject.Filename;
layoutObjectName$ = layoutObject.Name;
layoutObjectNumber = layoutObject.Number;
IniWriteString("DOQQSML", "Layout", layoutFileName$);
GetInputRaster(DOQQ);
GetInputVector(WetlandsVector);
doqqFileName$ = DOQQ.$INFO.Filename;
doqqObjectName$ = DOQQ.$INFO.Name;
doqqObjectDesc$ = DOQQ.$INFO.Desc;
doqqObjectNumber = DOQQ.$INFO.Number;
IniWriteString("DOQQSML", "DOQQRaster", doqqFileName$);
templateDir$ = FileNameGetPath(layoutFileName$);
##############################################################################
# step 1: 
# Prompt for the output *.prf file.  Use the directory the user puts this
# file into as the "workDir".  Prevent it from being the same directory as
# the template for sanity's sake.
############################################################################## 
# XXX The work directory name should be derived from the DOQQ raster 
# name, but The GetFile dialog won't default to a nonexistant
# directory.  
workDir$ = IniReadString("DOQQSML", "WorkDir");
# PRF file has same name as DOQQ file, but change the "1" to a "5"
#  example:		brand1sw.rvc -> brand5sw.prf
name$ = FileNameGetName(doqqFileName$);
if (NumberTokens(name$, "1") == 2) {
	name$ = GetToken(name$, "1", 1) + "5" + GetToken(name$, "1", 2); 
	}
prffile$ = workDir$ + "/" + name$ + ".prf";
prffile$ = GetOutputFileName(prffile$, 
			"Select output print file.  The layout and other\n"
		 + "files will be placed in this directory as well.", 
		 	"prf");
workDir$ = FileNameGetPath(prffile$);
# Keep the user from puting the workDir in the same place as the
# tempDir, as this would be bad. ("I'm a little fuzzy on this whole
# good-bad thing.")
while (workDir$ == templateDir$) {
	PopupMessage(
				"You can't create the new layout in the same directory as\n" 
			 + "the template layout.  Please choose a different directory."
				);
	prffile$ = GetOutputFileName(prffile$, 
				"Select output print file.  The layout and other\n"
			 + "files will be placed in this directory as well.", 
				"prf");
	workDir$ = FileNameGetPath(prffile$);
	}
IniWriteString("DOQQSML", "WorkDir", workDir$);
##############################################################################
# step 3: 
# edit ccs755.txt - change date on last line to current date
# Note we don't actually write out any file here.  The text is just
# held in a string variable and placed into the text layer directly.
##############################################################################
# The format string (2nd parameter) to DateToString can contain the following
# codes which it will replace with the information shown
#
#	%a  abbreviated weekday name
#	%A  Full weekday name
#  %b  abbreviated month name
#  %B  Full month name
#  %d  Day of the month ( 01 - 31 )
#  %e  Day of the month (  1 - 32; single digits preceded by a space)
#  %m  month number (01 - 12)
#  %y  year within century (00-99)
#  %Y  four digit year
currentDate$ = DateToString(Date(), "%e %B %Y");
inFile$ = templateDir$ + "/ccs755.txt";
numLines = CountLines(inFile$);
ccs755$ = "";
inFile = fopen(inFile$, "r");
numeric i;
for i = 1 to (numLines - 1) {
	line$ = fgetline$(inFile);
	ccs755$ = ccs755$ + line$ + "\n";
	}
line$ = fgetline$(inFile);
line$ = left$(line$, 6) + currentDate$;
ccs755$ = ccs755$ + line$ + "\n";
fclose(inFile);
##############################################################################
# step 4: 
# get date of photography from DOQQNAMEs metadata
# change IMG_DATE.TXT to this date
##############################################################################
db = OpenDatabase(templateDir$ + "/doqqmeta.rvc", "Database");
table = DatabaseGetTableInfo(db, "DOQQMETA");
photodate = 0;
quadname$ = "";
name$ = FileNameGetName(doqqFileName$);
for i = 1 to table.NumRecords {
	reqfilen$ = TableReadFieldStr(table, "REQFILEN", i);
	direct$ = TableReadFieldStr(table, "DIRECT", i);
	a$ = reqfilen$ + "1" + direct$;
	if (name$ == a$) {
		photodate = TableReadFieldNum(table, "PHOTODATE", i);
		quadname$ = TableReadFieldStr(table, "QUADNAME", i);
		dftcont = TableReadFieldNum(table, "CONTRAST", i);
		dftbright = TableReadFieldNum(table, "BRIGHTNESS", i);
		}
	}
if (!photodate) {
	photodate$ = PopupString(
'The metadata for this DOQQ (' + name$ + ') is empty or missing.
Please type the date of the photography as you wish it to 
appear on the map here (mm/dd/yy):');
	}
else {
	#photodate$ = DateToString(photodate, "%e %B %Y");  # 5 January 1996
	photodate$ = DateToString(photodate, "%m/%d/%y");	 # 01/05/96
	}
CloseRaster(DOQQ);
imgdate$ = "Date of photography: " + photodate$ + "\n";
wantNeatLine = IniReadNumber("DOQQSML", "WantNeatLine", false);
wantNeatLine = PopupYesNo("Do you want a neatline around the map image area?", wantNeatLine);
IniWriteNumber("DOQQSML", "WantNeatLine", wantNeatLine);
##############################################################################
# step 4b: 
# We got the title from the metadata too (assuming we found it)
##############################################################################
if (quadname$ == "") {
	# Didn't find one in the metadata.  Default to doqq object description
	maptitle$ = doqqObjectDesc$;
	}
else {
	ntokens = NumberTokens(quadname$, " ");
	maptitle$ = GetToken(quadname$, " ", 1); 
	for i = 2 to (ntokens - 1) {
		maptitle$ = maptitle$ + " " + GetToken(quadname$, " ", i);
		}
	# The last token will be the direction.  Insert a comma after it.
	if (ntokens > 1) {
		maptitle$ = maptitle$ + ", " + GetToken(quadname$, " ", ntokens);
		}
	}
contrast = 50;
brightness = 100;
if (dftcont) contrast = dftcont;
if (dftbright) brightness = dftbright;
##############################################################################
# step 4d: 
# Prompt for title, contrast and brightness values
##############################################################################
class PromptStr promptTitle;
class PromptNum promptCont, promptBright;
class XmForm dlg;
proc CB_Close() {
	maptitle$ = promptTitle.value;
	contrast = promptCont.value;
	brightness = promptBright.value;
	DialogClose(dlg);
	}
dlg = CreateModalFormDialog("Settings");
promptTitle = CreatePromptStr(dlg, "Title:", 64, maptitle$);
promptTitle.TopWidget = dlg;
promptTitle.LeftWidget = dlg;
promptTitle.RightWidget = dlg;
promptCont = CreatePromptNum(dlg, "Contrast:", 4, 0, contrast, 0, 100);
promptCont.TopWidget = promptTitle;
promptCont.LeftWidget = dlg;
promptBright = CreatePromptNum(dlg, "Brightness:", 4, 0, brightness, 0, 200);
promptBright.TopWidget = promptTitle;
promptBright.LeftWidget = promptCont;
sep = CreateHorizontalSeparator(dlg);
sep.TopWidget = promptBright;
sep.LeftWidget = dlg;
sep.RightWidget = dlg;
br = CreateButtonRow(dlg, CreatePushButtonItem("ok", CB_Close));
br.TopWidget = sep;
br.LeftWidget = dlg;
br.RightWidget = dlg;
br.BottomWidget = dlg;
DialogWaitForClose(dlg);
DestroyWidget(dlg);
##############################################################################
# step 2: (moved) 
# copy DOQQNAME from MERLIN data servers (in /RASTERS/DOQQ)
# Copy DNR Wetland vector from MERLIN data server (in VECTORS/DNRWET)
#
# Make sure  they're not already there.  We might want to prompt the 
# user and ask them if they want to do this.  If the source is already on 
# a local harddrive or the network connection is reasonably fast, there's 
# no reason to copy them.  But there's no way we can tell if this is the case.
##############################################################################
if (PopupYesNo("Do you wish to copy the DOQQ raster and Wetlands\n vector to the work directory?", true)) {
	if (FileNameGetPath(doqqFileName$) != workDir$) {
		CloseRaster(DOQQ);
		newname$ = workDir$ + "/" + FileNameGetName(doqqFileName$) + ".rvc";
		CopyFile(doqqFileName$, newname$);
		# Now need to reopen the object because we use that instead of the
		OpenRaster(DOQQ, doqqFileName$, doqqObjectName$); 
		CloseRaster(DOQQ);
		}
	oldname$ = WetlandsVector.$INFO.Filename;
	objname$ = WetlandsVector.$INFO.Name;
	if (FileNameGetPath(oldname$) != workDir$) {
		newname$ = workDir$ + "/" + FileNameGetName(oldname$) + ".rvc";
		CopyFile(oldname$, newname$);
		OpenVector(WetlandsVector, newname$, objname$); 
		CloseVector(WetlandsVector);
		}
	}
##############################################################################
# step 5: 
# Open LAYOUT.RVC/DOQQ_Wetland_v - change description to DOQQNAME
##############################################################################
layout = LayoutCreate("layout", 1);
LayoutRead(layout, layoutFileName$, layoutObjectName$);
##############################################################################
# step 6: 
# Verify print settings
##############################################################################
#layout.Hardcopy.Printer = "HP DesignJet 650C";
layout.Hardcopy.Printer = "HP DesignJet Series Color 300dpi";
layout.Hardcopy.MapScale = 8400;
layout.Hardcopy.RasterDitherPattern = "Stucki";
layout.Hardcopy.VectorDitherPattern = "weave";	# Internal name of "vector"
layout.Hardcopy.FullPage = true;
layout.Hardcopy.dpi = 300;
layout.Hardcopy.Contrast = contrast;
layout.Hardcopy.Brightness = brightness;
IniWriteString("PRINTERS", "PortType", "file");
IniWriteString("PRINTERS", "PortName", prffile$);
IniWriteString("PRINTERS", "PRFFile", prffile$);
##############################################################################
# step 7: 
# Change the title
##############################################################################
group = LayoutGetGroupByName(layout, "Title");
textlayer = group.FirstLayer;
textstyle.Font = "times.ttf";
textstyle.Height = 1.25;  # inches
textstyle.LineSpace = .3228;	# Inches
textstyle.MapScale = layout.Hardcopy.MapScale;
textstyle.UseLayoutScale = 1;
textstyle.Foreground.Name = "black";
textstyle.Background.Name = "white";
textlayer.Text = maptitle$;
textlayer.Style = textstyle;
##############################################################################
# step 8: 
# Remove the DOQQ raster and wetlands vector
#	(Dont actually do this here.  Well replace the objects in the
#	existing layers instead)
# Instead, find the actual layers
##############################################################################
mapgroup = LayoutGetGroupByName(layout, "Map Data");
layer = mapgroup.FirstLayer;
while (layer) {
	if (layer.Type == "Raster") rastlayer = layer;
	if (layer.Type == "Vector") vectlayer = layer;
	if (layer.Type == "Map Grid") gridlayer = layer;
	layer = layer.NextLayer;
	}
##############################################################################
# step 9: 
# Re add the new DOQQ
##############################################################################
RasterLayerSetObject(rastlayer, DOQQ);
rastlayer.NullCellsTransparent = false;
##############################################################################
# step 10a: 
# Re add the new Wetlands vector.
##############################################################################
VectorLayerSetObject(vectlayer, WetlandsVector);
vectlayer.Point.Select.Mode = "None";
vectlayer.Node.Draw = false;
vectlayer.StyleObject = OpenStyleObject(templateDir$ + "/styles.rvc", "STYLES");
##############################################################################
# step 10b: 
# Set the line styles
##############################################################################
vectlayer.Line.Select.Mode = "ByAttribute";
vectlayer.Line.StyleMode = "ByAttribute";
vectlayer.DrawLinesFirst = false;	# Don't draw lines before polygons
tinfo = TableGetInfo(WetlandsVector.line.ClassStyle);
tinfo.StyleObjName = "";
numeric num = NumRecords(WetlandsVector.line.ClassStyle);
string cl$, l$;
for i = 1 to num {
	cl$ = WetlandsVector.line.ClassStyle[@i].Class$;
	if (cl$ == "Unclassified") {
		WetlandsVector.line.ClassStyle[@i]._DrawFlag_ = 0;
		}
	else {
		WetlandsVector.line.ClassStyle[@i]._DrawFlag_ = 1;
		l$ = left$(cl$, 1);
		if (l$ == "E") {
			WetlandsVector.line.ClassStyle[@i]._StyleName_$ = "Estuarine_Lin";
			WetlandsVector.line.ClassStyle[@i]._StyleIndex_ = 1;
			}
		else if (l$ == "P") {
			WetlandsVector.line.ClassStyle[@i]._StyleName_$ = "Palustrine_Lin";
			WetlandsVector.line.ClassStyle[@i]._StyleIndex_ = 4;
			}
		else if (l$ == "R") {
			WetlandsVector.line.ClassStyle[@i]._StyleName_$ = "Riverine_Lin";
			WetlandsVector.line.ClassStyle[@i]._StyleIndex_ = 2;
			}
		else {
			# Assume "break line" or "lead line"
			# Instructions say "or similar", but can't tell 
			WetlandsVector.line.ClassStyle[@i]._StyleName_$ = "Break_Lead_Line";
			WetlandsVector.line.ClassStyle[@i]._StyleIndex_ = 0;
			}
		}
	}
##############################################################################
# step 10c: 
# Set the polygon styles
##############################################################################
vectlayer.Poly.Select.Mode = "ByAttribute";
vectlayer.Poly.NoFill = false;	# Don't disable polygon filling
tinfo = TableGetInfo(WetlandsVector.poly.ClassStyle);
tinfo.StyleObjName = "";
num = NumRecords(WetlandsVector.poly.ClassStyle);
for i = 1 to num {
	WetlandsVector.poly.ClassStyle[@i]._DrawFlag_ = 1;
	WetlandsVector.poly.ClassStyle[@i]._StyleName_$ = "Wetland";
	WetlandsVector.poly.ClassStyle[@i]._StyleIndex_ = 0;
	}
##############################################################################
# step 10d: 
# Set the Label styles
##############################################################################
vectlayer.Label.Draw = true;
labelstyle.Font = "mallard.of";
labelstyle.Foreground.Name = "yellow";
labelstyle.Background.Name = "black";
labelstyle.Enhance = true;
labelstyle.UseElemHeight = true;
vectlayer.Label.NormalStyle = labelstyle;
##############################################################################
# step 11: 
# Change group settings for the "Map Data" group
##############################################################################
# Need the extents of the DOQQ raster layer in degrees
georef = GeorefAlloc();
GeorefSetProjection(georef, latlon);
GetObjectExtents(DOQQ, xmin, ymin, xmax, ymax, georef);
GeorefFree(georef);
# Set the ClipRegion to this rect + a 2 second buffer
halfsize = (7.5 / 4) / 60;	# Half the height of a quarter quad in degrees
twosec = 2.0 / 3600;			# Two seconds converted to degrees
cx = (xmin + xmax) / 2;
cy = (ymin + ymax) / 2;
# Force center to fall on a the correct interval
# Floor rounds to -infinity.
cx = floor(cx / halfsize + .5) * halfsize;
cy = floor(cy / halfsize + .5) * halfsize;
extents.x1 = cx - halfsize - twosec;
extents.x2 = cx + halfsize + twosec;
extents.y1 = cy - halfsize - twosec;
extents.y2 = cy + halfsize + twosec;
# Need to set clip region to this rectangle
mapgroup.ClipRegion.SetFromRect(extents);
mapgroup.ClipRegion.Projection = latlon;
mapgroup.Clip = true;
mapgroup.X.AttachTo = "Margin";
mapgroup.X.AttachThis = "Left";
mapgroup.X.AttachRef = "Left";
mapgroup.X.Offset = .2;	# Page inches
mapgroup.Y.AttachTo = "Margin";
mapgroup.Y.AttachThis = "Center";
mapgroup.Y.AttachRef = "Center";
mapgroup.Y.Offset = -.5;	# Page inches
##############################################################################
# step 12: 
# Modify the mapgrid
##############################################################################
if (gridlayer) LayerDestroy(gridlayer);
gridlayer = GroupAddMapGridLayer(mapgroup, projection, 5000, 5000, "feet", latlon, extents);
LayerRaise(vectlayer);	# Move vector layer back on top
gridlayer.Name = projection.System;
gridlayer.CoordFormat = "Comma";
gridlayer.BorderRelative = false;	# Starting At: Origin
gridlayer.ShowBorder = false;
gridlayer.LayoutScale = true;
gridlayer.ShowCoordText2D = true;
gridlayer.CoordLabelStyle = textstyle;
gridlayer.CoordLabelStyle.Foreground.name = "black";
gridlayer.CoordLabelStyle.Height = .1;	# Inches, approx 2.5 mm
gridlayer.ShowGrid = true;
gridlayer.GridStyle.Color.name = "white";
gridlayer.GridWidthUnits = "mm";
gridlayer.GridWidth = .5;
# Border ticks are off.  To offset text by a bit, turn them
# on, but keep them white so they don't show up
gridlayer.ShowBorderTicksExt = false;
gridlayer.ShowBorderTicksExt = false;
gridlayer.BorderTickWidthUnits = "mm";
gridlayer.BorderTickWidth = .5;
gridlayer.BorderTickOutsideUnits = "mm";
gridlayer.BorderTickOutside = 2.0;
gridlayer.BorderTickStyle.Color.name = "white";
##############################################################################
# step 13: 
# Modify the CCWS Text group
##############################################################################
group = LayoutGetGroupByName(layout, "CCWS Text");
textlayer = group.FirstLayer;
textstyle.Height = .315; # approx 8 mm
textlayer.Style = textstyle;
textlayer.Text = ccs755$;
##############################################################################
# step 14: 
# Modify the Photo Date text layer
##############################################################################
group = LayoutGetGroupByName(layout, "Photo Date");
textlayer = group.FirstLayer;
textstyle.Height = .157; # approx 4 mm
textlayer.Style = textstyle;
textlayer.Text = imgdate$;
##############################################################################
# step 16: (Changed the order here on purpose)
# Use object editor to edit the neatline vector.  Id change this to use
# an SML layer to autogenerate a neatline.  (This is an option Maryland
# didnt have when they started this project)
#
# Heres an even easier way.  Create a mapgrid but only show the border
# The neatline will then be exactly on the quarter quad border.
##############################################################################
# We had expanded the extents out by two seconds for clipping.  Now put them
# back to the actual quarter quad bounds.
extents.x1 = extents.x1 + twosec;
extents.x2 = extents.x2 - twosec;
extents.y1 = extents.y1 + twosec;
extents.y2 = extents.y2 - twosec;
# Neatline was done with a vector.  Delete it
layer = GroupGetLayerByName(mapgroup, "NEATLINE / Neatline");
if (layer) LayerDestroy(layer);
if (wantNeatLine) {
	neatlayer = GroupAddMapGridLayer(mapgroup, latlon, 1, 1, "degrees", latlon, extents);
	neatlayer.Name = "NEATLINE / Neatline";
	neatlayer.ShowGrid = false;
	neatlayer.ShowCoordText2D = false;
	neatlayer.ShowBorderTicksExt = false;
	neatlayer.ShowBorderTicksInt = false;
	neatlayer.ShowBorder = true;
	neatlayer.LayoutScale = true;
	# XXX Change the color of the neatline in the main map here...
	neatlayer.BorderStyle.Color.name = "red";	# name from RGB.txt
	neatlayer.BorderWidthUnits = "mm";
	neatlayer.BorderWidth = .5;
	}
##############################################################################
# Step 16a:  There's a neatline in the index map too.  Same drill
##############################################################################
indexgroup = LayoutGetGroupByName(layout, "Index Map");
# Neatline was done with a vector.  Delete it
layer = GroupGetLayerByName(indexgroup, "NEATLINE / Neatline");
if (layer) LayerDestroy(layer);
neatlayer = GroupAddMapGridLayer(indexgroup, latlon, 1, 1, "degrees", latlon, extents);
neatlayer.Name = "NEATLINE / Neatline";
neatlayer.ShowGrid = false;
neatlayer.ShowCoordText2D = false;
neatlayer.ShowBorderTicksExt = false;
neatlayer.ShowBorderTicksInt = false;
neatlayer.ShowBorder = true;
neatlayer.LayoutScale = true;
# XXX This is the color of the rectangle in the index map
neatlayer.BorderStyle.Color.name = "red";
neatlayer.BorderWidthUnits = "mm";
neatlayer.BorderWidth = .5;
neatlayer.SizeRelative = true;
neatlayer.LayoutScale = false;
neatlayer.MapScale = layout.MapScale / indexgroup.RelScale;
##############################################################################
# step 15: (Changed the order here on purpose)
# Save the layout
##############################################################################
string newFileName$ = workDir$ + "/layout.rvc";
CopyFile(layoutFileName$, newFileName$);
layoutFileName$ = newFileName$;
DeleteObject(layoutFileName$, layoutObjectNumber);	# Remove old layout
LayoutWrite(layout, layoutFileName$, layoutObjectName$, doqqObjectDesc$);
##############################################################################
# step 17: 
# 	View / Print to generate print file, then save and exit
##############################################################################
numeric err = LayoutPageSetupDialog(layout);
#define SML_DEFINE_SML_MDISP_FUNC_LIST
if (!err && PopupYesNo("Do you want to print the layout now?", true)) {
	LayoutPrint(layout);
	}
# If we don't destroy the layout, it will prevent view from being able to
# exit.
LayoutDestroy(layout);
#
#	rvcmain 4.131 4618
#  rvcdbase.c 4.273 1260
#  qqobject.c 1.138 1196
#  doqq.sml --- 165
#
#  Need better error if the database isn't found
#
#  setting style object on vector layer seems to fail if it had no style
#	assigned to begin with.  May be that if vector was originally set to
#		"From vector" it ignores the style object I set
#