'ArcView 3.0a Avenue Script: Profiler Ver 1.0
'
'Use to create chart profiles of line features (streams, roads, trails, etc.) using a line theme 
'and an elevation grid theme.  
'
'Requires Spatial Analyst Extension.
'
'Requires two active themes, The first a line theme and the second a grid theme of elevations.  
'
'Requires lines to be selected. In general, selected lines should be connected for results 
'to be realistic. There is no programmatic check to ensure selected lines are connected. In general, selected lines
'should not contain multiple branching for results to be realistic. That is, each node should connect no more than
'two _selected_ line segments. 
'
'Merges selected lines then finds interval points along the merged line at equal intervals.  User is queried for how 
'many divisions of merged line. 
'
'Queries active grid theme cells for elevation values at interval points.
'
'Outputs a dbf file of distances starting at the lowest interval point and includes all interval points
'and corresponding z values. 
'   
'Outputs a line graph (profile) of distance from origin vs. z values if no more 
'than about 100 interval points are produced. Use a more robust graphing package to graph larger outputs.  
'
'Bill Eichenlaub
'bill_eichenlaub@nps.gov 
'
'Date: 5/18/98

theView       = av.getActiveDoc
thePrj        = theView.GetProjection


if (thePrj.IsNull) then
  hasPrj = false
  msgbox.warning("The data needs to be projected"
        +NL+"into a cartesian coordiante system","Projection Needed - Exiting!")
  exit
else
  hasPrj = true
end

err1 = "The first active theme must be a polyline theme, the second active theme must be a grid.  Click, hold and drag to change theme order.  Use SHIFT click to select more than one theme. "

if (theView.GetActiveThemes.Count <> 2) then
 msgbox.error(err1,"You need two selected themes...")
 return(nil)
end

theFTheme     = theView.GetActiveThemes.Get(0)

if (theFTheme.is(FTHEME)) then
  theFTab = theFtheme.GetFTab
else
  MsgBox.Error (err1 ,"The first selected theme is not a polyline theme...")
  return(nil)
end

theClassName = theFTab.GetShapeClass.GetClassName
if ((theClassName = "Polyline").Not) then
  MsgBox.Error (err1,"The first selected theme is not a polyline theme...")
  return(nil)
end

theGTheme = theView.GetActiveThemes.Get(1)
if (theGTheme.is(GTHEME))then
  theGrid = theGTheme.GetGrid
else
  MsgBox.Error (err1,"The second selected theme is not a Grid theme...")
  return(nil)
end
    
theGraphics   = theView.GetGraphics

theSet = theFtab.GetSelection
if (theSet.count = 0) then
  MsgBox.Error ("The active polyline theme must have at least one selected line.","Try Again...")
  return(nil)
end

theShapeIn    = theFTab.FindField("Shape")

'for each rec in the bit, merge into a polyline
c =0
for each rec in theSet
  theLine=theFtab.ReturnValue(theShapeIn, rec)
  if (c = 0) then
    allLines = theLine
  else
    allLines = allLines.returnMerged(theLine)
  end
  c=c+1
end

allLines.clean

ddd = graphicShape.make(allLines.returnProjected(thePrj))
theGraphics.addbatch(ddd)

'get the length of the resulting line
lineLength = allLines.returnProjected(thePrj).returnLength

'get number of divisions from user
numDivisions = msgbox.input("The selected lines total " + lineLength.asString  + " units in length.  They will be copied, merged and divided into even length intervals to produce the table and graph. How many divisions?","Profiler","10")
if (numDivisions = nil)then
  exit
end
numDivisions = numDivisions.asNumber

lengthPerDiv = lineLength/numDivisions
percentInc = (lengthPerDiv/lineLength)*100

startPt = allLines.asList.get(0).get(0)
centerPt = allLines.returnCenter
startPtZ = theGrid.CellValue (startPt, thePrj)
centerPtZ = theGrid.CellValue (centerPt, thePrj)
if (startPtZ > centerPtZ) then
  allLines.flip
end

theList = {}

'disect the line
dist = 0 
for each i in 0..100 by percentInc
  eachPt = allLines.Along(i)  
  'theGraphics.Add(graphicShape.Make(eachPt.clone.returnProjected(thePrj)))
  theZ = theGrid.CellValue (eachPt, thePrj)
  theList.add({eachPt, dist, theZ, "Segment", i.clone})
  dist = dist + lengthPerDiv
end


'make a dbf file and vtab to store the distance and z data
MADefault = fileName.make("$HOME").makeTmp("StrPr_","dbf")
MAOutput  = fileDialog.put( MADefault,"*.dbf","Output table of line lengths and elevations." )
if (MAOutput = nil) then
  theFTab.SetSelection(theSet)
  theFTab.UpdateSelection
  msgBox.info("No name entered, procedure cancelled","Exiting Procedure")
  return nil
end
MAOutput.setExtension("dbf")
theVtab = Vtab.makeNew(MAOutput, dbase)
theMeanATable = table.make(theVtab)
fSamNum = field.make("Num", #FIELD_SHORT, 5, 0)
fDistance = field.make("Distance", #FIELD_DOUBLE, 15, 1)
fzVal = field.make("Elevetion", #FIELD_DOUBLE, 15, 1)
fiVal = field.make("Per_Dist", #FIELD_DOUBLE, 15, 4)
ftype = field.make("Type", #FIELD_CHAR, 10, 0)
theVTab.addFields({fSamNum, fDistance, fzVal, ftype, fiVal})
'add the data 
count = 0
for each k in theList
  mDistance = k.get(1)
  mzVal = k.get(2)
  mtype = k.get(3) 
  miVal = k.get(4)
  rec= theVtab.addRecord
  theVtab.setValue(fSamNum, rec, count)
  theVtab.setValue(fDistance, rec, mDistance)
  theVtab.setValue(fzVal, rec, mzVal)
  theVtab.setValue(fiVal, rec, miVal)
  count=count+1
end
theMeanATable.SetName(MAOutput.asString + "_Profile_Table")

'chart the grid values vs. the line end points
if(theList.count < 100) then  
  'make a chart of the Mean Area data
  theDistance = theVtab.FindField("Distance")
  newChart = Chart.make(theVTab, {fzVal})
  newChart.SetRecordLabelField(theDistance)  
  newChart.SetSeriesFromRecords(false)
  newChart.GetChartDisplay.SetType(#CHARTDISPLAY_LINE)
  newChart.GetChartDisplay.SetSeriesColor (0, Color.GetBlue) 
  anXAxis = newChart.GetXAxis
  anXAxis.SetName ("Distance")
  anXAxis.SetLabelVisible (True)
  anYAxis = newChart.GetYAxis
  anYAxis.SetName ("Elevation")
  anYAxis.SetLabelVisible (True)
  newChart.GetTitle.SetName("Themes used: " + theFTheme.GetName+ " and "+ theGtheme.GetName)   
  newChart.getChartLegend.SetVisible (false)
  newChart.SetName(MAOutput.asString + "_Profile_Chart")
  newChart.GetWin.Open
else
  msgbox.info("No graph produced because the number of points used is greater than or equal to 100, the maximum which can be graphed.","Line Profiler")
end

theGraphics.endBatch
theGraphics.Invalidate


