Basically I have a graph that is bound from a DataTable which source is from a DataGridView. I have zoomable functions on the graph and I need it use X Axis SelectionStart and SelectionEnd in order to calculate the block of data that is selected.
So I have some minimums maximums and averages placed in a richtextbox on another tab. As shown below in the code:
//To show the Data from file into the TextBox
richTextBox1.AppendText("\n" + "Heart Average : " + HRM.Active.DataRows.Average(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Heart Minimum : " + HRM.Active.DataRows.Min(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Heart Maximum : " + HRM.Active.DataRows.Max(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Average Speed (KM/H): " + HRM.Active.DataRows.Average(r => r.Speed) + "\n");
richTextBox1.AppendText("\n" + "Maximum Speed : " + HRM.Active.DataRows.Max(r => r.Speed) + "\n");
richTextBox1.AppendText(Environment.NewLine + " - (MPH): " + "");
richTextBox1.AppendText("\n" + "Average Power: " + HRM.Active.DataRows.Average(r => r.Power) + "\n");
richTextBox1.AppendText("\n" + "Maximum Power : " + HRM.Active.DataRows.Max(r => r.Power) + "\n");
richTextBox1.AppendText("\n" + "Average Altitude (KM/H): " + HRM.Active.DataRows.Average(r => r.Altitude) + "\n");
richTextBox1.AppendText("\n" + "Maximum Altitude : " + HRM.Active.DataRows.Max(r => r.Altitude) + "\n");
richTextBox1.AppendText("\n" + "Cadence Average : " + HRM.Active.DataRows.Average(r => r.Cadence) + "\n");
richTextBox1.AppendText("\n" + "Cadence Maximum : " + HRM.Active.DataRows.Max(r => r.Cadence) + "\n");
richTextBox1.AppendText("\n" + "Pressure Average : " + HRM.Active.DataRows.Average(r => r.Pressure) + "\n");
richTextBox1.AppendText("\n" + "Pressure Maximum : " + HRM.Active.DataRows.Max(r => r.Pressure) + "\n");
Now in the image below you can see the image of the Graph and the data it shows on there, Here is the code which binds the datatable to the graph.
protected void drawChart()
{
DataTable dt = new DataTable();
dt.Clear();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
dt.Columns.Add(col.HeaderText);
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dRow = dt.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dt.Rows.Add(dRow);
}
Now what I need to do is have another textbox near the Graph and every time I zoom and the grey block comes out it displays the minimums maximiums and averages for the block i have selected! Then when I zoom out it resets to the original.
If you do not understand what I mean just message me and I will give more information.
To update a statistical calculation based on the visible Points after zooming or scrolling you need know two things: When should you do it and which points are visible.
The event to use is AxisViewChanged, that's easy. After you have hooked it up you can call a function to update your statistics:
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
updateStats();
}
The difficult part is to know which portion of the Points collection is visible.
At first glance you may think that the ViewEventArgs parm helps; after all it has such promising data as: NewPosition and NewSize.
But looking closer you will see that both are doubles, so unless your XValues have been set counting up from 0 by 1, they won't index into the Points collection.
Instead we must do a little searching for those values, from left for the minimum and from the right for the maximum. Here is a function to do so:
int getVisiblePoint(Chart chart, Series series, bool first)
{
Series S = series;
ChartArea CA = chart.ChartAreas[S.ChartArea];
DataPoint pt = null;
if (first) pt = S.Points.Select(x => x)
.Where(x => x.XValue >= CA.AxisX.ScaleView.ViewMinimum)
.DefaultIfEmpty(S.Points.First()).First();
else pt = S.Points.Select(x => x)
.Where(x => x.XValue <= CA.AxisX.ScaleView.ViewMaximum)
.DefaultIfEmpty(S.Points.Last()).Last();
return S.Points.IndexOf(pt);
}
From here on things get a lot easier; we can do statistics on our series, maybe like this:
void updateStats()
{
int firstPt = getVisiblePoint(chart1, chart1.Series[0], true);
int lastPt = getVisiblePoint(chart1, chart1.Series[0], false);
int sCount = chart1.Series.Count;
double[] avg = new double[sCount];
double[] min = new double[sCount];
double[] max = new double[sCount];
for (int i = 0; i < sCount; i++)
{
Series S = chart1.Series[i];
avg[i] = getAverage(S, firstPt, lastPt);
min[i] = getMixMax(S, firstPt, lastPt, true);
max[i] = getMixMax(S, firstPt, lastPt, false);
}
// insert code to display the data here!
}
using simple functions to do the math:
double getAverage(Series series, int first, int last)
{
double sum = 0;
for (int i = first; i < last; i++) sum += series.Points[i].YValues[0];
return sum / (last - first + 1);
}
double getMixMax(Series series, int first, int last, bool min)
{
double val = 0;
for (int i = first; i < last; i++)
{
double v = series.Points[i].YValues[0];
if ( (min && val > v) || (!min && val >= v)) val = v;
}
return val;
}
Related
public class Convert
{
public void MMtofeetfraction(float millimeters)
{
if ((millimeters % 304.8f) != 0)
{
int feet = (int)(millimeters / 304.8f);
double inchWithDecimal = millimeters * 0.03937;
string s = inchWithDecimal.ToString("0.0000");
string[] parts = s.Split('.');
int i1 = int.Parse(parts[0]);
float i2 = float.Parse("0." + parts[1]);
int inch = i1 % 12;
var accuracy = 16;
double num = 1;
double frac = i2 * accuracy;
num = Math.Round(frac);
if (num != 0)
{
while (num % 2 == 0)
{
num = num / 2;
accuracy = accuracy / 2;
}
if (inch != 0)
{
Debug.Log("Fraction output: " + feet + "'-" + inch + " " + num + "/" + accuracy + "\"");
}
else
{
Debug.Log("Fraction output: " + feet + "'-" + num + "/" + accuracy + "\"");
}
}
else
{
Debug.Log("Fraction output: " + feet + "'-" + inch + "\"");
}
}
else
{
Debug.Log("Fraction output: " + Math.Round(millimeters / 304.8) + "'");
}
}
}
Input 1440 : output : 4' 7 1/2"
Input 1550 : output : 5' 1 "
Input 1530 : output : 5' 1/4"
Now, this code works and gives output as needed. I was looking to improvise this code by removing string splitting and other string formatting. Can someone help with inbuilt functions to handle this?
IN C# i am trying to solve a problem :
Write a program that checks whether the product of the odd elements is equal to the product of the even elements.
The only thing left is:
On the second line you will receive N numbers separated by a whitespace.
I am unable to get this working. I have tried with Split but it keeps breaking. Can someone help?
Example:
Input
5
2 1 1 6 3
Output
yes 6
static void Main(string[] args)
{
long N = long.Parse(Console.ReadLine());
long[] array = new long[N];
long ODD = 1;
long EVEN = 1;
for (int i = 0; i < N; i++)
{
array[i] = int.Parse(Console.ReadLine());
if ((i + 1) % 2 == 0)
{
EVEN *= array[i];
}
else
{
ODD *= array[i];
}
}
if (EVEN == ODD)
{
Console.WriteLine("yes" + " " +
ODD);
}
else
{
Console.WriteLine("no" + " " + ODD + " " + EVEN);
}
}
Read from console input and keep it to an string array, Then convert each array element to long and apply the Odd Even logic like below:
static void Main(string[] args)
{
string input = Console.ReadLine();
string[] inputArray = input.Split(' ');
long element;
long odd = 1;
long even = 1;
foreach (var i in inputArray)
{
element = long.Parse(i);
if (element % 2 == 0)
{
even *= element;
}
else
{
odd *= element;
}
}
Console.WriteLine("\nOdd product = " + odd + ", Even product = " + even);
if (odd == even)
{
Console.WriteLine("ODD == EVEN \n");
Console.WriteLine("Yes" + " " + odd);
}
else
{
Console.WriteLine("ODD != EVEN \n");
Console.WriteLine("No" + " " + odd + " " + even);
}
Console.ReadKey();
}
long[] nums = input.Split(' ').Select(x => long.Parse(x))..ToArray(); //split numbers by space and cast them as int
int oddProduct = 1, evenProduct = 1; // initial values
foreach(long x in nums.Where(a => a%2 == 1))
oddProduct *= x; // multiply odd ones
foreach(long x in nums.Where(a => a%2 == 0))
evenProduct *= x; // multiply even ones
private void multiBtn_Click(object sender, EventArgs e)
{
for (int a = 1; a <= 10; a++)
for (int b = 1; b <= 10; b++)
lblTable.Text = (a + " * " + b + " = " + (a * b));
for (int a = 1; a <= 10; a++)
for (int b = 1; b <= 10; b++)
lblTable.Text += (a + " * " + b + " = " + (a * b));
}
It's doing exactly what I want it to do when it comes to multiplying. It's just not lined up in rows. It prints out the multiplication for integers 1 to 10. I just need them in rows and columns, could anyone explain to me how to do that through a label. really don't know how to explain what it's doing but in my gui it prints out like "10*10=1001*1=11*2=21*3=3" and so on it just keeps going like that. I'm not even sure why it starts out with 10*10=100
Try using the newline character, which will put each item on a new row. For columns, it is a little trickier. Using a fixed width font and some padding around the numbers should do.
First, the newline code addition:
lblTable.Text += (a + " * " + b + " = " + (a * b) + "\n");
Or, a preferred format for many is to use string.Format for the string:
lblTable.Text += (string.Format("{0} * {1} = {2}\n", a, b, (a * b)));
To get them to align, you can use the PadLeft string method. In the example below, I am assuming that a and b will have less than or equal to two digits, and a * b will have less than or equal to 3 digits (remember this will only work if you use a fixed-width font, like Consolas):
for (int a = 1; a <= 10; a++)
{
for (int b = 1; b <= 10; b++)
{
lblTable.Text += (string.Format("{0} * {1} = {2}\n",
a.ToString().PadLeft(2),
b.ToString().PadLeft(2),
(a * b).ToString().PadLeft(3)));
}
}
It's pretty unclear what it is exactly you want. But note that you can insert newline characters between each line (Environment.NewLine) to force a line-break, to have text displayed on successive rows (lines) in the Label.
For example:
lblTable.Text += a + " * " + b + " = " + (a * b) + Environment.NewLine;
I am making a
Waterfall chart in a PowerPoint add-in using VSTO.
PowerPoint.Slide slide = null;
PowerPoint.Shape shape = null;
PowerPoint.Chart chart = null;
This lines tells what kind of chart to make.
shape = slide.Shapes.AddChart(Office.XlChartType.xlColumnStacked, 200, 200, 300, 200);
This line here opens an Excel workbook which makes the chart when data is added into it.
chart = shape.Chart;
Here is an image of the chart that I create.
Now the problem is, I want the 2nd bar to be plotted form the end of the 1st bar i.e from 4 instead of 0 on the x-axis.
Like this.
Can someone tell me is there any way I can draw my series from the value of the previous series instead of 0 value of x-axis?
I don't think Excel or PowerPoint charts supports waterfalls out of the box. However, you can do this by keeping the chart type as stacked and adding a separate helper chart series that is invisible and pushes the other series up. Then it is all about calculating the different values for this helper chart series based on the previous values of the actual chart series.
By invisible, I imply making both the line and the fill none. The chart series will still be there, but you just won't see it unless you start editing the chart.
I created waterfall chart from Stacked column chart and used the Workbook object from the Chartdata of the Selected shape.
You can follow this link to check how to create waterfall chart manually..and then manipulate the Worksheet/datasheet of the chart through code to create Waterfall chart.
Here is a snippet of my code..
private void calculationAndFormatting(bool excelEvent,Excel.Worksheet Sheet)
{
//unregister from Excel Change Event
Sheet.Application.EnableEvents = false;
int lRow = 1;
lRow = iRowCount;
Sheet.Range["A1", "A" + lRow].Copy(Type.Missing);
Sheet.Range["B" + (lRow + 5)].PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
Sheet.Range["B1", "B" + lRow].Copy(Type.Missing);
Sheet.Range["A" + (lRow + 5)].PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
Sheet.Range["B1", "D1"].Copy(Type.Missing);
Sheet.Range["C" + (lRow + 5)].PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
int ulRow = Sheet.UsedRange.Rows.Count;
int k=ulRow;
if (!excelEvent)
{
Sheet.Range["C" + (lRow + 6)].Value = "0";
Sheet.Range["C" + (ulRow + 1)].Value = "0";
Sheet.Range["A" + (ulRow + 1)].Value = "=SUM(A" + (lRow + 5) + ":" + "A" + ulRow + ")";
Sheet.Range["B" + (ulRow + 1)].Value = "Total Value";
k = ulRow + 1;
}
for (int i = lRow + 6; i <= k; i++)
{
if (Sheet.Range["A" + i].Value < 0)
{
if (i <= k-1 && i != lRow + 6)
{
Sheet.Range["C" + i].Formula = "=E" + (i - 1) + "+" + "A" + i;
}
Sheet.Range["D" + i].Formula = "=-A" + i;
Sheet.Range["E" + i].Formula = "=C" + i;
}
else
{
if (i <= k-1 && i != lRow + 6)
{
Sheet.Range["C" + i].Formula = "=E" + (i - 1);
}
Sheet.Range["D" + i].Formula = "=A" + i;
Sheet.Range["E" + i].Formula = "=C" + i + "+" + "D" + i;
}
}
string sourceCol = "='" + Sheet.Name + "'!$C$" + (lRow + 5) + ":$E$" + (k);
pChart.SetSourceData(sourceCol, PowerPoint.XlRowCol.xlColumns);
PowerPoint.Axis axis = pChart.Axes(PowerPoint.XlAxisType.xlValue);
axis.MaximumScale = 1.25 * (System.Double)Sheet.Range["D" + (k)].Value;
axis.MinimumScale = 0.0;
PowerPoint.Axis catAxis = pChart.Axes(PowerPoint.XlAxisType.xlCategory);
catAxis.CategoryNames = Sheet.Range["B" + (lRow + 6), "B" + (k)].Value;
applyFormatting();
drawLeaderLines(Sheet);
Sheet.Application.EnableEvents = true;
Sheet = null;
}
I was able to solve the Collatz conjecture algorithm (no, i didn't try to prove it) in about 5 minutes using Java.
Now that I'm learning C# to make web apps, I'm running into trouble doing the same thing.
I simply want the user to enter a number, click a button, and print the output to a text box.
Here is the button Click event handler method I'm using:
protected void Button3_Click(object sender, EventArgs e)
{
string x = TextBox1.Text; //user entered a number
string y =collatz(x); //this function is below and returns a string
chatbox.Text = y; //output
}
And here is the Collatz method:
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y); //x is my "n"
y = x.ToString(); //output string
double large = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > large)
large = x;
if (x != 1)
y = y+" "+ x.ToString();
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
if (x % 2 != 0)
{
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y+" "+ x.ToString();
}
}
return y;
}
EDIT
when I use the VS.net debugger and enter a number like 2, I get NO output and NO error. I'm just left waiting forever. If it were an infinite loop, I would get an error eventually, right?
and no, this is not a homework problem (it was 2 years ago when I did it in JAVA though :).) I'm learning C# independently.
You had an infinite loop. Try this:
public static string collatz(string y)
{
if (y == null)
{
return null;
}
int x = int.Parse(y); //x is my "n"
var results = new StringBuilder();
results.Append(x.ToString());
int largest = x; //keep track of biggest number
// the algorithm
// the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
while (x > 1)
{
if (x % 2 == 0)
{
x = x / 2;
if (x > largest)
{
largest = x;
}
if (x != 1)
{
results.Append(" " + x.ToString());
}
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
}
if (x % 2 != 0)
{
if (x == 1)
{
results.Append(" " + x.ToString());
results.Append(" largest number was " + largest.ToString());
return results.ToString();
}
x = (3 * x) + 1;
if (x > largest)
{
largest = x;
}
results.Append(" " + x.ToString());
}
}
return results.ToString();
}
Two notes:
When you're doing string concatenation in a loop, it's a good habit to use a StringBuilder rather than s = s + t. Lots, lots less memory allocations.
A lot of times you can't rely on == when it comes to double values. It seems to work in this case, but it might not when you get to higher numbers where there's less precision. Since all the numbers are going to be int's anyway, might as well use those.
if (x == 1)
{
y = y+" "+ x.ToString();
y = y + " largest number was " + large;
}
This part here (odd x) is redundant. For if x is 1, it will never enter the while loop. Your code seems logically. Maybe try using integer instead.
x = x / 2;
if (x > large)
large = x;
Redundant code again for even x part. How do you expect x to be bigger than large after division by 2? Just check it in the 3n+1 part will do.
if (x == 1)
{
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
You can just leave this part out and let the while loop handle this check.
public static string collatz(string y)
{
if (y == null)
return null;
double x = double.Parse(y);
y = x.ToString();
double large = x;
while (x > 1) {
if (x % 2 == 0) {
x = x / 2; // x reassigned
if (x > large)
large = x;
if (x != 1)
y = y + " " + x.ToString();
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
}
// Infinite loop goes because of that
if (x % 2 != 0) { // double check on reassigned variable, use “else” instead
if (x == 1) {
y = y + " " + x.ToString();
y = y + " largest number was " + large;
}
x = (3 * x) + 1;
if (x > large)
large = x;
y = y + " " + x.ToString();
}
}
return y;
}
I tried it with fixed code (using else) and it works fine.
Also, you don't need double type since Collatz works with natural numbers. The following is a quick refactoring to add more .NET-ty to your code:
public static string collatz(string input)
{
int current = 0;
if (string.IsNullOrEmpty(input) || !int.TryParse(input, out current) || current < 1) {
return "Empty, not a number or less then 1";
}
int max = current;
while (current > 1) {
if (current % 2 == 0) {
current = current / 2; // current reassigned
if (current > max)
max = current;
if (current != 1)
input = input + " " + current.ToString();
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
} else {
if (current == 1) {
input = input + " " + current.ToString();
input = input + " largest number was " + max;
}
current = (3 * current) + 1;
if (current > max)
max = current;
input = input + " " + current.ToString();
}
}
return input;
}
View Equation:
if the number is even: n/2
if the number is odd: 3n+1
Step One:
Add a method called Collazt which returns a collection of objects of type int of class List<?>
public static List<int> Collazt(int n) {
List<int> data = new List<int>();
data.Add(n);
int resul = 0;
while (true) {
if (n == 1) {
break;
}
if ((n % 2) == 0)
{
resul = n / 2;
n = resul;
}
else {
resul = (n * 3) + 1;
n = resul;
}
data.Add(n);
}
return data;
}
Step Two:
We call the method in our main class.
static void Main(string[] args)
{
Console.Write("N: ");
int r = int.Parse(Console.ReadLine());
List<int> result = Collazt(r);
Console.WriteLine("Lista:");
Console.WriteLine("[");
for (int i= 0; i<result.Count; i++) {
Console.Write(result[i]+"\n");
}
Console.WriteLine("]");
}
string restart;
do
{
Console.WriteLine("Type a Whole Number");
double n = Convert.ToDouble(Console.ReadLine());
do
{double a = n;
if (n % 2 == 0)
{
Console.WriteLine("Even");
n = a / 2;
Console.WriteLine(n);
}
else
{
Console.WriteLine("Odd");
n = (3*a) + 1;
Console.WriteLine(n);
}
}
while (n != 1);
Console.WriteLine("Yo Wanna Restart? Type y and press enter");
restart = Console.ReadLine();
Console.Clear();
}
while (restart == "y");
Console.ReadKey(true);
(not a professional programmer, made it for fun, i know there are better ways)