Use of a Dictionary for Property Labels
Prerequisites
This video extends the classes in Topic – Creating a Single Table Database Object Storage and is part of Topic – Using Collection Classes
Summary
Topics covered in this video;
-Calculator
-Flow
-CircularChannel
-AsHTMLTable
-XMLPropertyObject
-Abstract Classes
-Strings
-PropertyLabels
-PropertyPlaces
-PropertyValue
-Reflection
Video
Reference Materials
Channel and CircularChannel classes
public Channel()
{
// Default Constructor
}
public override Dictionary<string, string> PropertyLabels()
{
var d = new Dictionary<string, string>();
d.Add("Flow", "Flow (cfs)");
d.Add("Slope", "Slope (fraction)");
d.Add("ManningsN", "Mannings N");
d.Add("Depth", "Depth (ft)");
d.Add("Velocity", "Velocity (fps)");
d.Add("HydraulicRadius", "Hydraulic Radius (ft)");
d.Add("FlowArea", "Flow Area (cf)");
d.Add("WettedPerimeter", "Wetted Perimeter (ft)");
return d;
}
public override Dictionary<string, int> PropertyPlaces()
{
var d = new Dictionary<string, int>();
d.Add("Flow", 1);
d.Add("Slope", 3);
d.Add("ManningsN", 3);
d.Add("Depth", 1);
d.Add("Velocity", 1);
d.Add("HydraulicRadius", 1);
d.Add("FlowArea", 2);
d.Add("WettedPerimeter", 2);
return d;
}
}
public class CircularChannel : Channel
{
public double Diameter { get; set; }
#region Static Methods
public override Dictionary<string, string> PropertyLabels()
{
var d = base.PropertyLabels();
d.Add("Diameter", "Diameter (in)");
return d;
}
public override Dictionary<string, int> PropertyPlaces()
{
var d = base.PropertyPlaces();
d.Add("Diameter", 1);
return d;
}
#endregion
#region Calculations
public void Calculate()
{
if (Slope != 0 && ManningsN != 0 && Flow != 0 && Diameter != 0)
{
Depth = CalculateDepth();
Velocity = CalculateVelocity();
return;
}
if (Slope != 0 && ManningsN != 0 && Depth != 0 && Diameter != 0)
{
Flow = CalculateFlow();
Velocity = CalculateVelocity();
return;
}
}
public double CalculateAngle()
{
// Uses Flow to calculate theta
double d = Diameter / 12;
double n = ManningsN;
if (d == 0) return 0;
if (n == 0) return 0;
if (ManningsN <= 0) return 0;
if (Flow > FullFlow()) return 2 * Math.PI;
double theta = 1.0;
double delta = 1.0;
double lastdelta = 0.0;
double incr = 0.5;
int iter = 0;
while (Math.Abs(delta) > 0.00001 && iter < 500)
{
double r = 0.25 * d * (1 - Math.Sin(theta) / theta);
double b = Flow / ((1.0 / 8.0) * (theta - Math.Sin(theta)) * Math.Pow(d, 2));
delta = (1.49 / n) * Math.Pow(r, 2.0 / 3.0) * Math.Pow(Slope, 0.5) - b;
if (Math.Sign(lastdelta) != Math.Sign(delta)) incr = incr / 2;
theta = (delta > 0 ? theta - incr : theta + incr);
lastdelta = delta;
if (theta > 2 * Math.PI) return 2 * Math.PI;
iter++;
}
return theta;
}
public double CalculateDepth()
{
// Using Flow Calculates Depth
if (Slope == 0) return 0;
if (Flow == 0) return 0;
if (ManningsN == 0) return 0;
double theta = CalculateAngle();
if (theta == 0) return 0;
double d = Diameter / 12;
double r = d / 2;
if (theta > 2 * Math.PI) return d;
if (theta < Math.PI)
{
double t = (Math.PI - theta) / 2;
return r - r * Math.Sin(t);
}
else
{
double t = (theta - Math.PI) / 2;
return r + r * Math.Sin(t);
}
}
public double CalculateVelocity()
{
// Uses Flow to Calculate depth
if (Slope == 0) return 0;
if (Flow == 0) return 0;
if (ManningsN == 0) return 0;
double d = Diameter / 12;
double r = d / 2;
if (Flow > FullFlow())
return Flow / (Math.PI * Math.Pow(r, 2));
double theta = CalculateAngle();
if (theta == 0) return 0;
FlowArea = Math.PI * Math.Pow(r, 2) * (theta / (2 * Math.PI));
Velocity = Flow/FlowArea;
return Velocity;
}
public double CalculateHydraulicRadius()
{
// uses depth to calculate Hydraulic Radius
if (Depth == 0) return 0;
if (Depth > Diameter / 12) return 0.5;
double r = Diameter / 24;
double a = CalculateFlowArea();
double p = CalculateWettedPerimeter();
HydraulicRadius = a/p;
return HydraulicRadius;
}
public double CalculateWettedPerimeter()
{
// uses depth to calculate Hydraulic Radius
if (Depth == 0) return 0;
if (Depth > Diameter / 12) return Math.PI * Diameter / 12;
double r = Diameter / 24;
if (Depth <= r)
{
double th = 2 * Math.Acos((r - Depth) / r);
double a = (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
double p = r * th;
WettedPerimeter = a/p;
return WettedPerimeter;
}
else // more than half full
{
double h = Diameter / 12 - Depth;
double th = 2 * Math.Acos((r - h) / r);
double a = Math.PI * Math.Pow(r, 2) - (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
double p = 2 * Math.PI * r - r * th;
return a / p;
}
}
public double CalculateFlow()
{
HydraulicRadius = CalculateHydraulicRadius();
FlowArea = CalculateFlowArea();
return (1.49 / ManningsN) * FlowArea * Math.Pow(HydraulicRadius, 2.0 / 3.0) * Math.Pow(Slope, 0.5);
}
public double FullFlow()
{
double d = Diameter / 12;
return (0.4644 / ManningsN) * Math.Pow(d, (8.0 / 3.0)) * Math.Pow(Slope, 0.5);
}
public double Capacity()
{
return FullFlow();
}
public double CalculateFlowArea()
{
if (Depth != 0)
{
double r = Diameter / 24;
if (Depth > Diameter / 12)
return Math.PI * Math.Pow(r, 2);
if (Depth <= r)
{
double th = 2 * Math.Acos((r - Depth) / r);
return (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
}
else // more than half full
{
double h = Diameter / 12 - Depth;
double th = 2 * Math.Acos((r - h) / r);
return Math.PI * Math.Pow(r, 2) - (Math.Pow(r, 2) * (th - Math.Sin(th))) / 2;
}
}
if (Flow != 0)
{
double r = Diameter / 24;
double theta = CalculateAngle();
if (theta == 0) return 0;
double area = Math.PI * Math.Pow(r, 2) * (theta / (2 * Math.PI));
return area;
}
return 0;
}
#endregion
public double[,] DepthAsArray()
{
int n = 20;
var v = new double[2, n];
for (int i = 0; i < n; i++)
{
v[0, i] = i * (Diameter / 12) / 20;
Depth = v[0, i];
v[1, i] = CalculateFlow();
}
return v;
}
}
public class TrapezoidalChannel : Channel
{
public double SideSlope { get; set; }
public double BottomWidth { get; set; }
public void Calculate()
{
if (Slope != 0 && ManningsN != 0 && Flow != 0 && BottomWidth != 0)
{
Depth = CalculateDepth();
Velocity = CalculateVelocity();
return;
}
if (Slope != 0 && ManningsN != 0 && Depth != 0 && BottomWidth != 0)
{
Flow = CalculateFlow();
Velocity = CalculateVelocity();
return;
}
}
public double CalculateDepth()
{
// Iteratively calculates depth
if (!CanCalculate()) return 0;
double b = BottomWidth;
double z = SideSlope;
double q = Flow;
double dh = 1.0;
double delta = 1.0;
double lastdelta = 1.0;
double incr = 0.1;
while (delta > 0.0001 && incr > 0.00001)
{
double area = (b + z * dh) * dh;
double wp = b + 2 * dh * Math.Sqrt(((1 + Math.Pow(z, 2))));
double hr = area / wp;
double dq = (1.49 / ManningsN) * area * Math.Pow(hr, 2 / 3) * Math.Sqrt(Slope);
delta = dq - q;
if (Math.Sign(delta) != Math.Sign(lastdelta)) incr = incr / 2;
if (delta > 0) dh -= incr;
if (delta < 0) dh += incr;
lastdelta = delta;
}
return dh;
}
public double CalculateFlowArea()
{
if (!CanCalculate()) return 0;
return Depth * (BottomWidth + SideSlope * Depth);
}
public double CalculateWettedPerimeter()
{
if (!CanCalculate()) return 0;
return BottomWidth + 2 * Depth * Math.Sqrt(1 + Math.Pow(SideSlope, 2));
}
public double CalculateHydraulicRadius()
{
if (!CanCalculate()) return 0;
return CalculateFlowArea() / CalculateWettedPerimeter();
}
public double CalculateVelocity()
{
if (!CanCalculate()) return 0;
double area = CalculateFlowArea();
return Flow / area;
}
public double CalculateFlow()
{
if (!CanCalculate()) return 0;
double area = CalculateFlowArea();
double hr = CalculateHydraulicRadius();
return (1.49 / ManningsN) * area * Math.Pow(hr, 2 / 3) * Math.Sqrt(Slope);
}
public Boolean CanCalculate()
{
if (Slope == 0) return false;
if (ManningsN == 0) return false;
if (Depth == 0) return false;
return true;
}
public double[,] DepthAsArray()
{
int n = 20;
double holdDepth = Depth;
double maxDepth = Depth * 2;
var v = new double[2, n];
for (int i = 0; i < n; i++)
{
v[0, i] = i * (maxDepth) / 20;
Depth = v[0, i];
v[1, i] = CalculateFlow();
}
Depth = holdDepth;
return v;
}
}
XmlPropertyObject class
public abstract class XmlPropertyObject : IXmlPropertyObject
{
public int id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Owner { get; set; }
public XmlPropertyObject(int ID)
{
id = ID;
Select(ID);
}
public XmlPropertyObject() { }
public string asXML()
{
// XML Serializer used to convert class to XML
XmlSerializer x = new XmlSerializer(this.GetType());
// Store the XML using a StringWriter
StringWriter writer = new StringWriter();
x.Serialize(writer, this);
// Return a String
return writer.ToString();
}
public Dictionary<String,String> AsDictionary()
{
var d = this.GetType().GetProperties().ToDictionary(property => property.Name, property => Convert.ToString(property.GetValue(this)));
return d;
}
public string className()
{
string fc = this.GetType().ToString();
while (fc.Contains("."))
{
fc = fc.Substring(fc.IndexOf(".") + 1);
}
return fc;
}
public string getPropertyFromXml(string property, string xml)
{
XDocument doc = XDocument.Parse(xml);
// Gets the value fom XML
try { return doc.Root.Element(property).Value; }
catch { return String.Empty; }
}
public void setID(int ID)
{
id = ID;
Select(ID);
}
public void setPropertyFromXml(string property, string xml)
{
string value = getPropertyFromXml(property, xml);
setProperty(property, value);
}
public string getPropertyValue(string name)
{
PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
return Convert.ToString(pi.GetValue(this));
}
public string getPropertyValue(string name, int places)
{
// Specifically to deal with numeric formats
string FormatString = "{0:N" + places.ToString().Trim()+"}";
PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
return String.Format(FormatString, pi.GetValue(this));
}
public void setProperty(string name, string value)
{
PropertyInfo pi = this.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
if (null != pi && pi.CanWrite)
{
pi.SetValue(this, Convert.ChangeType(value, pi.PropertyType), null);
}
}
public void setPropertiesFromXml(string xml)
{
XDocument doc = XDocument.Parse(xml);
foreach (XElement xe in doc.Root.Elements())
{
setProperty(xe.Name.ToString(), xe.Value);
}
}
public void Select(int ID)
{
DataTable dt = DatabaseXmlStore.Select(ID);
if (dt.Rows.Count == 0) return;
setPropertiesFromXml(dt.Rows[0]["XmlData"].ToString());
id = ID;
}
public DataTable SelectAll(string ownerID)
{
return DatabaseXmlStore.SelectAll(ownerID, className());
}
public string Insert()
{
return DatabaseXmlStore.Insert(this);
}
public string Update()
{
if (id == 0)
return Insert();
else
return DatabaseXmlStore.Update(this);
}
public string AsHtmlTable()
{
string s = "<table>";
foreach (KeyValuePair<string, string> pair in PropertyLabels())
{
s += "<tr>";
s += "<td>" + pair.Value + "</td>";
int p = PropertyPlaces()[pair.Key];
string v = getPropertyValue(pair.Key, p);
s += "<td>" + v + "</td>";
s += "</tr>";
}
s += "</table>";
return s;
}
public abstract Dictionary<string, string> PropertyLabels();
public abstract Dictionary<string, int> PropertyPlaces();
}