' ------------------------------------------------------------------------- ' GIS Laboratory ' Geological & Planetary Sciences Division ' Caltech ' ------------------------------------------------------------------------- ' Program : GPS.ContourSection ' Purpose : Generate a view and cross section theme using contour lines ' and a user-defined cross section line ' ------------------------------------------------------------------------- ' Calls : none ' Called by: GPS extension ' ------------------------------------------------------------------------- ' Arguments: none ' Globals : none ' ------------------------------------------------------------------------- ' Notes : theFTab is the table associated with the contour theme, ' theVTab is the table which contains the extracted elevations, ' newFTab is the table associated with the new elevations point ' theme ' ------------------------------------------------------------------------- ' History : 11/19/97 - Tony Soeller; script created ' ------------------------------------------------------------------------- '. ' ' Identify theView document and ' allow user to generate a graphical line theView = av.GetActiveDoc userLine = theView.ReturnUserLine if (userLine.IsNull) then return nil else grLine = GraphicShape.Make(userLine) theView.GetGraphics.UnselectAll grLine.SetSelected(FALSE) theView.GetGraphics.Add(grLine) av.GetProject.SetModified(true) end ' Extract the end points of the userline startPoint = userLine.ReturnStart endPoint = userLine.ReturnEnd x_start = startPoint.GetX y_start = startPoint.GetY x_end = endPoint.GetX y_end = endPoint.GetY ' Calculate angle from the starting point to the ' ending point of the cross section line ' (First handle the rare cases for a vertical cross section line) theXSide = x_end - x_start theYSide = y_end - y_start if (theXSide = 0) then baseAngle = 90 if (theYSide < 0) then baseAngle = 270 end else baseAngle = (theYSide / theXSide).ATan.AsDegrees if ((x_end < x_start) and (y_end >= y_start)) then baseAngle = 180 - baseAngle.Abs elseif ((x_end < x_start) and (y_end < y_start)) then baseAngle = 180 + baseAngle elseif ((x_end > x_start) and (y_end < y_start)) then baseAngle = 360 - baseAngle.Abs end end baseAngle = baseAngle * -1 ' Get the theme and FTab theThemeList = theView.GetActiveThemes if (theThemeList.Count < 1) then MsgBox.Warning("A contour theme must be active","") theView.GetGraphics.RemoveGraphic(grLine) return nil end theTheme = theThemeList.Get(0) theFTab = theTheme.GetFTab ' Construct those cute little tic marks on the end of the X-sec line ' The length of the tic is relative to the view extent theExtent = theView.GetDisplay.ReturnExtent theMax = theExtent.GetHeight.Max(theExtent.GetWidth) theRatio = 25 ' fraction of the max of view width or height ticLength = theMax / theRatio ticX = ticLength * (90 - baseAngle).AsRadians.Cos ticY = ticLength * (90 - baseAngle).AsRadians.Sin ticX1 = ticX + x_start ticY1 = ticY + y_start ticX2 = ticX + x_end ticY2 = ticY + y_end tic1 = GraphicShape.Make(Line.Make(x_start@y_start,ticX1@ticY1)) theView.GetGraphics.Add(tic1) tic2 = GraphicShape.Make(Line.Make(x_end@y_end,ticX2@ticY2)) theView.GetGraphics.Add(tic2) ' Assign the user's .dbf file theFileName = FileDialog.Put("cont_sec.dbf".AsFileName,"*.dbf", "Enter table name") if (theFileName = nil) then theView.GetGraphics.RemoveGraphic(grLine) theView.GetGraphics.RemoveGraphic(tic1) theView.GetGraphics.RemoveGraphic(tic2) return nil end ' Add the "A" and "A'" to the user's line textLength = 2 * (theMax / theRatio) textX = textLength * (90 - baseAngle).AsRadians.Cos textY = textLength * (90 - baseAngle).AsRadians.Sin textX1 = textX + x_start - (ticLength / 2) textY1 = textY + y_start - (ticLength / 2) textX2 = textX + x_end - (ticLength / 2) textY2 = textY + y_end - (ticLength / 2) textAngle = baseAngle * -1 if ((textAngle > 90) and (textAngle < 270)) then textAngle = textAngle - 180 end textLeft = GraphicText.Make("A",textX1@textY1) textLeft.SetAngle(textAngle) textLeft.SetDisplay(theView.GetDisplay) theView.GetGraphics.Add(textLeft) textRight = GraphicText.Make("A'",textX2@textY2) textRight.SetAngle(textangle) textRight.SetDisplay(theView.GetDisplay) theView.GetGraphics.Add(textRight) ' Group the line, tics and text into a single GraphicGroup grLine.SetSelected(true) tic1.SetSelected(true) tic2.SetSelected(true) textLeft.SetSelected(true) textRight.SetSelected(true) theView.GetGraphics.GroupSelected ' Attach the new cross section line to the contour theme theTheme.GetGraphics.Merge(theView.GetGraphics.GetSelected) theTheme.GetGraphics.RemoveDuplicates theTheme.GetGraphics.Invalidate theView.GetGraphics.UnselectAll ' Extract the attribute names from the currently selected ' line theme. (Drop the "Shape" attribute.) Allow user to ' choose the "Elevation" attribute. theFields = theTheme.GetFTab.GetFields.DeepClone theFields.Remove(0) theChoice = MsgBox.List(theFields.AsList, "Choose Elevation Attribute","Elevation") if (theChoice = nil) then MsgBox.Info("Operation cancelled","") return nil end theElevField = theChoice.AsString ' Construct the new VTab. Use the user's elevation field name as the ' new Z-field theVTab = VTab.MakeNew(theFileName,dBase) fields = List.Make fields.Add(Field.Make("X",#FIELD_DOUBLE,16,6)) fields.Add(Field.Make(theElevField,#FIELD_DOUBLE,16,6)) theVTab.AddFields(fields) XField = theVTab.FindField("X") YField = theVTab.FindField(theElevField) x_right = ((x_end - x_start) * baseAngle.AsRadians.Cos) - ((y_end - y_start) * baseAngle.AsRadians.Sin) shpField = theFTab.FindField("Shape") elevField = theFTab.FindField(theElevField) min_x = 99999999 max_x = 0 min_x_elev = 0 max_x_elev = 0 ' Visit each line in the FTab; find the intersection of the contour ' line with the cross section line; write the coordinates and ' attributes out to the new table; find the minimum contour line ' and the maximum contour line cut by the cross section line and ' write the associated elevation values out to the VTab using the ' x-values of 0 and that of the length of the cross section line. for each rec in theFTab thePolyLine = theFTab.ReturnValue(shpField,rec) theMultiPt = thePolyLine.PointIntersection(userLine) 'Note: we have to use a Multipoint opperation here because 'the cross section line might intersect an individual contour 'line more than once along its length for each thePoint in theMultiPt.AsList x_pt = thePoint.GetX - x_start y_pt = thePoint.GetY - y_start x_new = (x_pt * baseAngle.AsRadians.Cos) - (y_pt * baseAngle.AsRadians.Sin) newRec = theVTab.AddRecord theVTab.SetValue(XField,newRec,x_new) theElev = theFTab.ReturnValue(elevField,rec) theVTab.SetValue(YField,newRec,theElev) if (x_new < min_x) then min_x = x_new min_x_elev = theElev end if (x_new > max_x) then max_x = x_new max_x_elev = theElev end end end ' Get the resulting number of records in the new VTab. ' If there are none then cancel the table construction totalRecs = theVTab.GetNumRecords if (totalRecs < 1 ) then MsgBox.Warning("None of the contour lines are intersected by"+NL+ "the cross section line along its extent."+NL+ "The table will not be generated.","") theVTab.SetEditable(false) return nil end ' Add starting/ending records @ ends of cross section line newRec = theVTab.AddRecord theVTab.SetValue(XField,newRec,0) theVTab.SetValue(YField,newRec,min_x_elev) newRec = theVTab.AddRecord theVTab.SetValue(XField,newRec,x_right) theVTab.SetValue(YField,newRec,max_x_elev) theVTab.Refresh theVTab.SetEditable(false) ' Write the start and end points of the cross section line ' to the new table and include the name of the original point theme theTable = Table.Make(theVTab) theDict = Dictionary.Make(30) theDict.Add("x_start",x_start) theDict.Add("y_start",y_start) theDict.Add("x_end",x_end) theDict.Add("y_end",y_end) theDict.Add("source theme",theTheme.AsString) theTable.SetObjectTag(theDict) theComments = "Generated from"++theTheme.AsString++"using"++ x_start.AsString+","+y_start.AsString++"to"++ x_end.AsString+","+y_end.AsString theTable.SetComments(theComments) theTable.SetName(theFileName.GetBaseName.AsString) ' If desired, create a new view and add a point event theme to the view ' using the table of x-values and their associated elevation values. if (MsgBox.MiniYesNo("Do you want to add the elevation points to a new view?", true).not) then return nil end theFileName = FileDialog.Put("cont_pts.shp".AsFileName, "*.shp","Enter theme name") if (theFileName = nil) then return nil end newFTab = FTab.MakeNew(theFileName,point) ' Develop the fields list and add the fields to the FTab fields = List.Make fields.Add(Field.Make("X", #FIELD_DOUBLE,16,6)) fields.Add(Field.Make(theElevField,#FIELD_DOUBLE,16,6)) newFTab.AddFields(fields) ' Assign variable names for each field in the FTab shpField = newFTab.FindField("Shape") FTabXField = newFTab.FindField("X") FTabZField = newFTab.FindField(theElevField) theBitMap = theVTab.GetSelection totalRecs = theBitMap.GetSize if (totalRecs >= 1) then for each i in 0..(totalRecs - 1) theX = theVTab.ReturnValue(XField,i) theZ = theVTab.ReturnValue(YField,i) thePoint = theX@theZ 'Move the current value for each field into the specific field rec = newFTab.AddRecord newFTab.SetValue ( shpField, rec, thePoint ) newFTab.SetValueNumber ( FTabXField, rec, theX ) newFTab.SetValueNumber ( FTabZField, rec, theZ ) end end newFTab.Flush theNewView = View.Make theViewWin = theNewView.GetWin theViewWin.Open theFTheme = FTheme.Make(newFTab) theNewView.AddTheme(theFTheme) theFTheme.SetVisible(true) theFTheme.SetActive(true) av.GetProject.SetModified(true) ' Write the start and end points of the cross section line ' to the new theme and include the name of the original point theme theFTheme.SetObjectTag(theDict) theFTheme.SetComments(theComments)