' 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 and Sanitation
'              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