' Name: JuanitaPieGraphicsShape ' ' Title: Draw sector-pie graphical symbols from water quality data ' ' Topics: Views ' ' Description: Reads median chemical data from a file created outside ' ArcView, and plots Juanita Pie symbols at the monitoring points based on compliance ' with water quality guidelines. Originally an AML written by Juanita Moolman ' Institute for Water Quality Studies, Department of Water Affairs & Forestry ' Private Bag X313 PRETORIA South Africa 0001 ' MoolmanJ@dwaf.gov.za - Reworked for Avenue. ' ' Author: Michael Silberbauer 2001-03-12 ' ' Requires: A View, a data file ' ' Self: ' ' Results: ' ----------------------------------------------------------------------------- theView = av.GetActiveDoc theDisplay = theView.GetDisplay thePrj = theView.GetProjection ' Get the GraphicList for the View... theGraphics = theView. GetGraphics ' Return the extent (the enclosing rectangle) of the View: theMapExtent = theView.GetDisplay.ReturnVisExtent ' Extract the dimensions of the View from the extent: '+----------------------------+x2m,y2m '| | '| | '| | '| |ywm '| | '| | '| | '+----------------------------+ 'x1m,y1m xwm theLowerLeft = theMapExtent.ReturnOrigin x1m = theLowerLeft.Getx y1m = theLowerLeft.Gety xwm = theMapExtent.GetWidth ywm = theMapExtent.GetHeight x2m = x1m + xwm y2m = y1m + ywm theUpperRight = x2m@y2m y = 1 x = y * ( xwm / ywm ) theDiagonal = ((x ^2) + (y ^2)).sqrt 'Scale = theDiagonal / 100 Scale = ( x2m - x1m ) / 50 UseTypeList = ( { "Domestic_Health", "Domestic_Salts", "Irrigation" } ) UseMissing = MsgBox.YesNo( "Use incomplete records (can be very cluttered) ?", "JuanitaPie: Missing Records", FALSE ) LblSymbol = MsgBox.YesNo( "Label symbols with variable names (only for key) ?", "JuanitaPie: Label Symbols", FALSE ) IDSymbol = MsgBox.YesNo( "Label symbols with station names ?", "JuanitaPie: ID Symbols", FALSE ) UseType = MsgBox.ListAsString( UseTypeList, "Please choose a use type", "Juanita Pie: Choose use type" ) if( UseType = "Domestic_Health" ) then ' Allocate colours to the various components: theColourDict = Dictionary.Make( 256 ) theColourDict.Add( "medpH" ,{1,2,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medNO3(N)" ,{2,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medNH4(N)" ,{3,1,3, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medFluoride" ,{4,1,8, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 220,000,000, 190,000,000, 155,000,000, 125,000,000, 255,000,255 } ) theColourDict.Add( "medTDS" ,{5,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medTurbidity",{6,1,3, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) 'Set constants (type 1 quality decreases with concentration ' type 2 quality is best in the middle range) 'Use Dictionary (Keys: constituent, type of quality (e.g 2=pH or 1=other), ' number of breakpoints, breakpoints) UseVariables = Dictionary.Make( 256 ) UseVariables.Add( "medpH" ,{1,2,4, 4.0, 6.0, 9.0,11.0 } ) UseVariables.Add( "medNO3(N)" ,{2,1,4, 3.0, 6.0,10.0,20.0 } ) UseVariables.Add( "medNH4(N)" ,{3,1,3, 1.0, 2.0,10.0 } ) UseVariables.Add( "medFluoride" ,{4,1,8, 1.0, 1.5, 3.5, 4.0,6.0,8.0,100,2000} ) UseVariables.Add( "medTDS" ,{5,1,4, 450,1000,2000,3000 } ) UseVariables.Add( "medTurbidity",{6,1,3, 1.0, 5.0,10.0 } ) end if( UseType = "Domestic_Salts" ) then ' Allocate colours to the various components: theColourDict = Dictionary.Make( 256 ) theColourDict.Add( "medChloride" ,{1,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medSulphate" ,{2,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medMagnesium",{3,1,6, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 220,000,000, 190,000,000, 255,000,255 } ) theColourDict.Add( "medCalcium" ,{4,1,2, 000,000,255, 255,000,000, 255,000,255 } ) theColourDict.Add( "medSodium" ,{5,1,6, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 220,000,000, 190,000,000, 255,000,255 } ) theColourDict.Add( "medPotassium",{6,1,3, 000,000,255, 255,255,000, 255,000,000, 255,000,255 } ) 'Set constants (type 1 quality decreases with concentration ' type 2 quality is best in the middle range) 'Use Dictionary (Keys: constituent, type of quality (e.g 2=pH or 1=other), ' number of breakpoints, breakpoints) UseVariables = Dictionary.Make( 256 ) UseVariables.Add( "medChloride" ,{1,1,4, 100, 200, 600, 1200 } ) UseVariables.Add( "medSulphate" ,{2,1,4, 200, 400, 600, 1000 } ) UseVariables.Add( "medMagnesium",{3,1,6, 30, 50, 70, 100, 200, 400 } ) UseVariables.Add( "medCalcium" ,{4,1,2, 32, 80 } ) UseVariables.Add( "medSodium" ,{5,1,6, 100, 200, 400, 600, 1000, 5000 } ) UseVariables.Add( "medPotassium",{6,1,3, 50, 100, 400 } ) end if( UseType = nil ) then MsgBox.Info( "Nothing selected", "Juanita Pies EXIT" ) return nil end if( UseType = "Irrigation" ) then ' Allocate colours to the various components: theColourDict = Dictionary.Make( 256 ) theColourDict.Add( "medSAR" ,{1,1,3, 000,000,255, 000,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medChloride" ,{2,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medConductivity" ,{3,1,4, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 255,000,255 } ) theColourDict.Add( "medBoron" ,{4,1,6, 000,000,255, 000,255,000, 255,255,000, 255,000,000, 220,000,000, 190,000,000, 255,000,255 } ) theColourDict.Add( "medpH" ,{5,3,2, 000,000,255, 255,000,000, 255,000,255 } ) 'Set constants (type 1 quality decreases with concentration ' type 2 quality is best in the middle range) 'Use Dictionary (Keys: constituent, type of quality (e.g 2=pH or 1=other), ' number of breakpoints, breakpoints) UseVariables = Dictionary.Make( 256 ) UseVariables.Add( "medSAR" ,{1,1,3, 2, 8, 15 } ) UseVariables.Add( "medChloride" ,{2,1,4, 100, 175, 350, 700 } ) UseVariables.Add( "medConductivity" ,{3,1,4, 40, 90, 270, 540 } ) UseVariables.Add( "medBoron" ,{4,1,6, 0.5, 1, 2, 4, 6, 15 } ) UseVariables.Add( "medpH" ,{5,3,2, 6.5, 8.4 } ) end if( UseType = nil ) then MsgBox.Info( "Nothing selected", "Juanita Pies EXIT" ) return nil end UseKeys = UseVariables.ReturnKeys nPetals = 0 for each key in UseKeys nPetals = nPetals + 1 end pi = Number.GetPi angrad = pi / 180 Radius = 1 theProject = av.getProject if( LblSymbol ) then theTable = theProject.FindDoc( "keydata.txt" ) theTable = theProject.FindDoc( "keytestdata.txt" ) else theTable = theProject.FindDoc( "olifants_data.txt" ) end theVTab = theTable.getVTab numrecs = theVTab.GetNumRecords FieldList = theVTab.GetFields shortlist = List.Make for each fieldname in FieldList if( fieldname.asString.Left( 3 ) = "med" ) then shortlist.Add( fieldname ) 'MsgBox.Info( fieldname.AsString, "FIELD" ) end end 'selfields = MsgBox.MultiListAsString( shortlist, "Choose fields (Shift to select many)", "SELECT FIELDS TO PLOT" ) 'if( selfields = nil ) then ' MsgBox.Info( "NO FIELDS SELECTED", "Stopping execution" ) ' return nil 'else ' nPetals = selfields.count ' MsgBox.Info( nPetals.AsString, "Number of petals" ) 'end av.ShowStopButton av.ShowMsg("Starting process...") for each record in theVTab 'for each record in 1 .. 10 theField = theVtab.FindField ("Station") station = theVtab.ReturnValue (theField, record) theField = theVtab.FindField ("Latitude") lat = theVtab.ReturnValue (theField, record) theField = theVtab.FindField ("Longitude") lon = theVtab.ReturnValue (theField, record) theField = theVtab.FindField ("Station") station = theVtab.ReturnValue (theField, record) theGraphicGroup = GraphicGroup.Make geopoint = Point.Make( lon, lat ) prjpoint = geopoint.ReturnProjected( thePrj ) xSymbol = prjpoint.GetX ySymbol = prjpoint.GetY ItemsList = List.Make ClassList = List.Make SeqnsList = List.Make ValueList = List.Make classtring = station Valid = true if( UseMissing.Not ) then 'Check that all the values required for the symbol are available: for each fieldname in FieldList if( fieldname.asString.Left( 3 ) = "med" ) then for each key in UseKeys if( fieldname.asString = key.AsString ) then keyList = UseVariables.Get( key ) theField = theVTab.FindField( key ) theValue = theVtab.ReturnValue ( theField, record ) if( theValue < 0 ) then Valid = false end end end end end end if( Valid ) then for each fieldname in FieldList if( fieldname.asString.Left( 3 ) = "med" ) then for each key in UseKeys if( fieldname.asString = key.AsString ) then keyList = UseVariables.Get( key ) theField = theVTab.FindField( key ) theValue = theVtab.ReturnValue ( theField, record ) seqnum = keyList.Get( 0 ) type = keyList.Get( 1 ) ncuts = keyList.Get( 2 ) ncutsn = ncuts + 2 if( theValue < 0 ) then 'Set the class to "missing" (-1): class = -1 end 'Match the value to the cutpoints: if( type = 1 ) then if( theValue >= 0 ) then class = 0 end class = ncuts for each ncut in ncutsn .. 3 by -1 'why must arrays start at 0?! cutpoint = keyList.Get( ncut ) if( theValue < cutpoint ) then class = ncut - 3 end end end if( type = 2 ) then ' the tricky case of domestic pH: if( theValue >= 0 ) then class = 0 end cutpoint1 = keyList.Get( 4 ) cutpoint2 = keyList.Get( 5 ) if( ( theValue > cutpoint1 ) and ( theValue < cutpoint2 ) ) then class = 0 end cutpoint3 = keyList.Get( 3 ) cutpoint4 = keyList.Get( 6 ) if( ( theValue > cutpoint3 ) and ( theValue <= cutpoint1 ) ) then class = 1 end if( ( theValue >= cutpoint2 ) and ( theValue < cutpoint4 ) ) then class = 1 end if( ( theValue <= cutpoint3 ) or ( theValue >= cutpoint4 ) ) then class = 2 end end if( type = 3 ) then ' the tricky case of agricultural pH: if( theValue >= 0 ) then class = 0 end cutpoint1 = keyList.Get( 3 ) cutpoint2 = keyList.Get( 4 ) if( ( theValue > cutpoint1 ) and ( theValue < cutpoint2 ) ) then class = 0 end if( ( theValue <= cutpoint1 ) or ( theValue >= cutpoint2 ) ) then class = 1 end end if( class > 0 ) then 'MsgBox.Info( key.AsString++"="++class.AsString++"("++theValue.AsString++")", station ) end if( theValue < 0 ) then 'Set the class to "missing" (-1): class = -1 end classtring = classtring++key.AsString++"="++class.AsString ClassList.Add( class ) ItemsList.Add( key ) SeqnsList.Add( seqnum ) ValueList.Add( theValue ) end end end end nowDate = Date.Now nowDate.SetFormat( "yyyy-MM-dd" ) nowTime = Date.Now nowTime.SetFormat( "hhhh:m:s" ) dtStamp = nowDate.asString++" "++nowTime.AsString av.SetStatus( 100 * ( record / numrecs ) ) av.ShowMsg( dtStamp++record.AsString++classtring ) ' Calculate the dimensions of the Juanita pie diagram: XCentre = 0.0 YCentre = 0.0 PetAngle = 360 / nPetals TotalArea = pi * Radius^2 SegmentArea = TotalArea / nPetals 'Calculate a constant base area: BaseArea = SegmentArea / 4 BaseRadius = ( BaseArea / pi ).sqrt xcirc = ( XCentre * Scale ) + xSymbol ycirc = ( YCentre * Scale ) + ySymbol RadiusCirc = BaseRadius * Scale aCircle = Circle.Make ( xcirc@ycirc, RadiusCirc ) gCircle = GraphicShape.Make(aCircle) aSymbol = RasterFill.Make aSymbol.SetColor(Color.GetWhite) aSymbol.SetOLColor(Color.GetBlack) gCircle.SetSymbol(aSymbol) gCircle.SetObjectTag( "JuanitaPie" ) theGraphicGroup.Add( gCircle ) Petal = 0 for each ClassValue in ClassList Petal = Petal + 1 if( ClassValue >= 0 ) then Item = ItemsList.Get( Petal-1 ) Value_item = ValueList.Get( Petal-1 ) AngNum = SeqnsList.Get( Petal-1 ) NumClasses = UseVariables.Get( Item ).Get( 2 ) Type = UseVariables.Get( Item ).Get( 1 ) SeqNum = UseVariables.Get( Item ).Get( 0 ) ' if( ClassValue = 0 ) then ItmArea = BaseArea ItmRadius = BaseRadius else ItmArea = ( SegmentArea - BaseArea ) * ( ( ClassValue + 1 ) / ( NumClasses / Type ) ) ItmArea = BaseArea + ItmArea ItmRadius = ( ItmArea / pi ).sqrt end StartAngle = SeqNum * PetAngle 'MsgBox.Info( Value_item.AsString++"Class"++ClassValue.AsString,Petal.AsString++Item.AsString++StartAngle.AsString++"°" ) AngList = List.Make nvs = 4 for each nv in 0 .. nvs AngList.Add( StartAngle + ( PetAngle * ( nv / nvs ) ) ) end theVtxList = List.Make theVtxList.Add( xcirc@ycirc ) for each angvalue in AngList theVtxX = ItmRadius * (angrad * angvalue ).cos xv = ( theVtxX * Scale ) + xSymbol theVtxY = ItmRadius * (angrad * angvalue ).sin yv = ( theVtxY * Scale ) + ySymbol theVtxList.Add( xv@yv ) end theVtxList.Add( xcirc@ycirc ) mPol = polygon.Make( { theVtxList } ) gmPol= GraphicShape.Make( mPol ) aSym = RasterFill.Make ColIndx1 = ( ClassValue + 1 ) * 3 ColIndx2 = ColIndx1 + 1 ColIndx3 = ColIndx1 + 2 Rval1 = theColourDict.Get( Item ).Get( ColIndx1 ) Rval2 = theColourDict.Get( Item ).Get( ColIndx2 ) Rval3 = theColourDict.Get( Item ).Get( ColIndx3 ) aCol = Color.Make aCol.SetRGBList( { Rval1, Rval2, Rval3 } ) aSym.SetColor( aCol ) gmPol.SetSymbol(aSym) theGraphicGroup.Add( gmPol ) if( LblSymbol ) then ItemText = GraphicText.Make( Item, theVtxList.Get( ( theVtxList.Count / 2 ).round - 1 ) ) ItemAngle = StartAngle + ( PetAngle * 0.5 ) if( ( ItemAngle < 270 ) and ( ItemAngle > 90 )) then ItemAngle = ItemAngle + 180 end if( ItemAngle > 360 ) then ItemAngle = ItemAngle - 360 end ItemText.SetAngle( ItemAngle ) ItemText.SetObjectTag( "JuanitaPie" ) ItemSymbol = ItemText.ReturnSymbols.Get( 0 ) ItemSymbol.SetSize( 10 ) theGraphics.Add( ItemText ) end 'theGraphics.Invalidate end end if( IDSymbol ) then IDText = GraphicText.Make( station.AsString.Left( 6 ), xcirc@ycirc ) IDTextSymbol = IDText.ReturnSymbols.Get( 0 ) IDTextSymbol.SetSize( 4 ) theGraphicGroup.Add( IDText ) end theGraphicGroup.SetObjectTag( "JuanitaPie" ) theGraphics.Add( theGraphicGroup ) theGraphics.Invalidate end end av.ClearMsg av.ClearStatus theGraphics.Invalidate