Points on chart graphic don't fit y-lines - c#

Points on my second chart don't fit y-axis as you can see here:
Points values are exactly 50.0000, 49.9999, 49.9998 and 50.0001. But they are not on lines. And when I add point and with it increase number of values on y-axis, then points would fit y-axis, like in this picture.
Here is my code (sorry for Serbian text values)
TacnostVage tacnost = bazaPodataka.UcitajTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text));
List<TestTacnostVage> testoviTacnost = bazaPodataka.UcitajTestoveTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text));
chart2.ChartAreas.Clear();
chart2.Series.Clear();
prikažiToolStripMenuItem.DropDownItems.Clear();
tabeluToolStripMenuItem.DropDownItems.Clear();
string format = Convert.ToString(vaga.Podeljak);
format = format.Remove(format.Length - 1, 1) + "0";
if (testoviTacnost.Count != 0)
{
for (int i = 0; i < tacnost.NominalneMase.Count(); i++)
{
ChartArea area = new ChartArea();
Series series = new Series();
area.AxisY.MajorGrid.LineColor = Color.LightGray;
area.AxisX.MajorGrid.LineColor = Color.LightGray;
area.AxisY.LabelStyle.Format = format;
area.BorderColor = Color.LightGray;
area.BorderDashStyle = ChartDashStyle.Solid;
area.AxisY.Interval = vaga.Podeljak;
area.Name = "ChartArea" + (i + 1);
series.ChartType = SeriesChartType.Point;
series.ChartArea = "ChartArea" + (i + 1);
series.Name = "Tačka" + (i + 1);
string text = "";
TegoviTacnostVaga tegoviTacnost = bazaPodataka.UcitajTegoveTacnostVage(Convert.ToString(dataGridView2.SelectedRows[0].Cells[2].Value), Convert.ToInt32(comboBox18.Text), i);
if (tegoviTacnost != null)
{
for (int j = 0; j < tegoviTacnost.Proizvodjac.Count(); j++)
{
text += tegoviTacnost.Proizvodjac[j] + " ";
text += tegoviTacnost.SerijskiBrojevi[j] + " ";
text += tegoviTacnost.NominalneMase[j] + "g";
text += (j == tegoviTacnost.Proizvodjac.Count() - 1 ? "" : "\n");
}
}
series.LegendText = (text == "" ? "Nema podataka" : text);
for (int j = 0; j < testoviTacnost.Count(); j++)
series.Points.AddXY(testoviTacnost[j].RedniBrojTesta, testoviTacnost[j].RezultatiMerenja[i]);
area.AxisY.StripLines.Add(new StripLine() { BorderColor = Color.Red, IntervalOffset = (tacnost.RezultatiMerenja[i].Average() + koeficijentTacnost * ponovljivost.ReferentnaVrednost), Text = "Gornja granica: " + Convert.ToDouble(tacnost.RezultatiMerenja[i].Average() + koeficijentTacnost * ponovljivost.ReferentnaVrednost).ToString(format) });
area.AxisY.StripLines.Add(new StripLine() { BorderColor = Color.Red, IntervalOffset = (tacnost.RezultatiMerenja[i].Average() - koeficijentTacnost * ponovljivost.ReferentnaVrednost), Text = "Donja granica: " + Convert.ToDouble(tacnost.RezultatiMerenja[i].Average() - koeficijentTacnost * ponovljivost.ReferentnaVrednost).ToString(format) });
area.AxisY.Maximum = area.AxisY.StripLines[0].IntervalOffset + area.AxisY.Interval;
if (series.Points.FindMaxByValue().YValues[0] >= area.AxisY.Maximum)
area.AxisY.Maximum = series.Points.FindMaxByValue().YValues[0] + area.AxisY.Interval;
area.AxisY.Minimum = area.AxisY.StripLines[1].IntervalOffset - area.AxisY.Interval;
if (series.Points.FindMinByValue().YValues[0] <= area.AxisY.Minimum)
area.AxisY.Minimum = series.Points.FindMinByValue().YValues[0] - area.AxisY.Interval;
chart2.ChartAreas.Add(area);
chart2.Series.Add(series);
}
}

I found solution, but I'm not sure if this explanation is true. The problem was Axis-Y maximum. Charts Axis-Y interval was 0.0001 (4 decimals), but in my code, I put maximum to be StripLines IntervalOffset (which was more than 4 decimals) plus Charts Interval (in result that is more than 4 decimals). So probably this happens when your Chars Axis-Y Maximum and your Interval (if you set Interval) have different number of decimals. So I just simply rounded Strip Lines InvervalOffset to 4 decimals (in this case), and put Axis-Y Maximum to have 4 decimals like Interval has.

Related

C# chart with multiple series, each with different x axis

I'm trying to export data to excel file (working quite fine) and create a chart.
What I have: 3 columns - ID, value, date. There are multiple rows with same id, but different value and datetime.
Example:
ID - Value - Datetime
1 - 14 - 21.11.2017 2:17:08
1 - 15 - 22.11.2017 14:25:45
3 - 12.5 - 21.11.2017 15:12:12
3 - 18.7 - 21.11.2017 19:27:35
3 - 13 - 22.11.2017 0:47:17
What I want is a chart, where Value is Y axis, each ID is a series, and Datetime is X axis. However, the datetime is different for each ID.
This is how it should look, but with dates instead of numbers on the X axis.
Chart Image.
I've been searching for a solution, and trying solutions from similar questions, but none had been "on point" yet.
This is what I have so far:
Excel.ChartObjects ChartObjects = (Excel.ChartObjects)WS.ChartObjects();
Excel.ChartObject chartObject = ChartObjects.Add(400, 40, 450, 300);
chartObject.Chart.ChartType = Excel.XlChartType.xlXYScatterLines;
Excel.SeriesCollection oSeriesCollection = (Excel.SeriesCollection)chartObject.Chart.SeriesCollection();
Excel.Axis xAxis = (Excel.Axis)chartObject.Chart.Axes(Excel.XlAxisType.xlCategory, Excel.XlAxisGroup.xlPrimary);
xAxis.HasTitle = true;
xAxis.AxisTitle.Text = "Date";
Excel.Axis yAxis = (Excel.Axis)chartObject.Chart.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
yAxis.HasTitle = true;
yAxis.AxisTitle.Text = "Value";
int startPos = 4;
int endPos = 0;
int previousCount = 0;
for (int i = 0; i < Count; i++)
{
startPos = startPos + previousCount;
endPos = startPos + CountList[i].Count - 1;
Excel.Series oSeries = oSeriesCollection.NewSeries();
oSeries.Values = WS.Range["E" + startPos, "E" + endPos];
//oSeries.XValues = WS.Range["F" + startPos, "F" + endPos]; //doesn't really do anything
oSeries.Name = "id " + CountList[i].Number.ToString();
previousCount = CountList[i].Count;
}
If it makes any difference, date is datetime in database, but is converted to string when storing it in List.
How can I set the x axis the way I need it to be? Is it possible?
I did something very similar using EPPlus. It was in asp.net MVC 5, so saving the document might need to be altered to suit your needs. In my case reading age is the value you want to display on Y axis and they have dates on X axis. Hopefully this will at least you give you something to build on. Notice the comment within, otherwise the chart did not work as intended for me.
var results = GetResultsSomehow();
ExcelPackage excel = new ExcelPackage();
var workSheet = excel.Workbook.Worksheets.Add("Reading Ages");
workSheet.TabColor = System.Drawing.Color.Black;
var scatterChart = (ExcelScatterChart)workSheet.Drawings.AddChart("Reading Ages", eChartType.XYScatterSmooth);
scatterChart.SetPosition(3, 1, 4, 1);
scatterChart.SetSize(800, 500);
scatterChart.XAxis.Format = "dd/mm/yyyy";
// must display hidden data and empty as gaps, otherwise the date axis will explode
scatterChart.ShowHiddenData = true;
scatterChart.DisplayBlanksAs = eDisplayBlanksAs.Gap;
int rowIndex = 4;
int stopIndex = 4;
foreach (var student in results.Select(a=> a.Student).Distinct())
{
int start = rowIndex;
int stop = start + stopIndex;
workSheet.Cells[rowIndex, 1].Value = student.Surname;
foreach(var row in results.Where(a=> a.Student == student))
{
workSheet.Cells[rowIndex, 2].Value = row.Age;
workSheet.Cells[rowIndex, 3].Value = row.Date;
rowIndex++;
stopIndex++;
}
stop = rowIndex;
var series = scatterChart.Series.Add(workSheet.Cells[start, 2, stop - 1, 2], workSheet.Cells[start, 3, stop - 1, 3]);
series.Header = student.Surname;
}
string excelName = identifier + " reading ages";
using (var memoryStream = new MemoryStream())
{
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=" + excelName + ".xlsx");
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}

I want change variable to value of hashtables in arraylist

I made [Hashtable hash] such as
hash(i, 1)
hash(j, 2)
Also I made an [arraylist sArray] which include "i" or "j" such as
sArray[0] : hello
sArray[1] : first number is i
sArray[2] : second number is j
sArray[3] : bye
Now, I want to change the "i" and "j" in the sArray to the values of the hash.
How can I do it?
If I understand properly, I think this is the code in c#
//Your example
int i = 1;
int j = 2;
var hash = new System.Collections.Hashtable();
hash[i] = -173.5;
hash[j] = 37;
var sArray = new System.Collections.ArrayList();
sArray.Add("hello");
sArray.Add("first number is " + hash[i].ToString());
sArray.Add("second number is " + hash[j].ToString());
sArray.Add("bye");
// more general, you could have different i and j position
i = 3;
j = 4;
hash[i] = 33.3;
hash[j] = -44.4;
sArray[1] = "number in " + i.ToString() + " position is " + hash[i].ToString();
sArray[2] = "number in " + j.ToString() + " position is " + hash[j].ToString();
// I think following option is more easy to read and fast if iterated
i = 5;
j = 6;
hash[i] = 55.5;
hash[j] = -66.6;
sArray[1] = String.Format("number in {0} position is {1}", i, hash[i]);
sArray[2] = String.Format("number in {0} position is {1}", j, hash[j]);

variable has different value then operator

First time poster, c# beginner.
Problem:
Some values result in incorrect calculations, though the operator shows a correct value (when hovering over it in debug)
Variable value should be: 49.9006...
But instead 47.4344... is stored.
Program:
Split a spiral into arc segments.
Input: straight line and a curve (curve being a circle or an arc)
Get Arc coordinates, center point & angle.
Code snippet: (all variables are defined as doubles, except for i & iNe as these are counters thus defined as int)
for (i = 0; i < 20; i++)
{
iNe = i + 1;
if (i == 0)
nRay = 0;
else
nRay = this.RadiusBase / i;
nRayNe = this.RadiusBase / iNe;
nAng = this.Alpha * i;
nAngNe = this.Alpha * iNe;
if (i == 0)
{
cumAng = 0;
cumAngNe = cumAng + nAngNe;
}
else
{
cumAng = nAng + cumAng;
cumAngNe = cumAng + nAngNe;
}
nSin = Math.Sin(cumAng);
nSinNe = Math.Sin(cumAngNe);
nCos = Math.Cos(cumAng);
nCosNe = Math.Cos(cumAngNe);
n1minCos = 1 - nCos;
nXjonc = nXcp + ((double)iNe * (nXcpNe - nXcp));
nYjonc = nYcp - ((double)iNe * (nYcp - nYcpNe));
What am i doing wrong?

How can I set NaN (Not a Number) to zero in SpinEdit Devexpress?

#Html.DevExpress().SpinEditFor(m => m.MLComPrice,
settings => {
settings.Properties.DisplayFormatString = "F";
settings.Properties.ValueChangedDelay = 1;
settings.Properties.MaxLength = 6;
settings.Properties.MinValue = 0;
settings.Properties.MaxValue = 100;
}).GetHtml()
If I digit only " , " in SpinEdit, it show NaN, how can I set this to Zero ?

Midpoint displacement algorithm - weird results

I am writing my own midpoint displacement algorithm for learning purposes and I decided to implement it in my own way to see if I was 1) able to understand the algorithm and 2) see if i could modify it to my liking.
here is the code to generate the fractal:
public void Generate(Double rg, int size)
{
Random rand = new Random();
int min = -127;
int max = 128;
// Starting points of the rectangle
MDP_Point s1 = new MDP_Point(0, 0, rand.Next(min, max));
MDP_Point s2 = new MDP_Point(size, 0, rand.Next(min, max));
MDP_Point s3 = new MDP_Point(size, size, rand.Next(min, max));
MDP_Point s4 = new MDP_Point(0, size, rand.Next(min, max));
// Lists containing the rectangles
List<MDP_Rect> newRect = new List<MDP_Rect>(); // Newly created rectangles
List<MDP_Rect> oldRect = new List<MDP_Rect>(); // Rectangles being divided
// Starting rectangle is added to the list
oldRect.Add(new MDP_Rect(s1, s2, s3, s4));
// Distance between 2 points in a rectangle
int h = size;
while (h > 1)
{
foreach (MDP_Rect r in oldRect)
{
// Middle points of rectangle segments
MDP_Point m1 = new MDP_Point();
MDP_Point m2 = new MDP_Point();
MDP_Point m3 = new MDP_Point();
MDP_Point m4 = new MDP_Point();
// Middle point of rectangle
MDP_Point mm = new MDP_Point();
m1.x = (r.C1.x + r.C2.x) / 2;
m1.y = (r.C1.y + r.C2.y) / 2;
m1.z = ((r.C1.z + r.C2.z) / 2) +(rand.Next(min, max) * rg);
m2.x = (r.C2.x + r.C3.x) / 2;
m2.y = (r.C2.y + r.C3.y) / 2;
m2.z = ((r.C2.z + r.C3.z) / 2) +(rand.Next(min, max) * rg);
m3.x = (r.C3.x + r.C4.x) / 2;
m3.y = (r.C3.y + r.C4.y) / 2;
m3.z = ((r.C3.z + r.C4.z) / 2) +(rand.Next(min, max) * rg);
m4.x = (r.C1.x + r.C4.x) / 2;
m4.y = (r.C1.y + r.C4.y) / 2;
m4.z = ((r.C1.z + r.C4.z) / 2) + (rand.Next(min, max) * rg);
mm.x = (r.C1.x + r.C2.x + r.C3.x + r.C4.x) / 4;
mm.y = (r.C1.y + r.C2.y + r.C3.y + r.C4.y) / 4;
mm.z = ((r.C1.z + r.C2.z + r.C3.z + r.C4.z) / 4) + (rand.Next(min, max) * rg);
newRect.Add(new MDP_Rect(r.C1, m1, mm, m4));
newRect.Add(new MDP_Rect(m1, r.C2, m2, mm));
newRect.Add(new MDP_Rect(mm, m2, r.C3, m3));
newRect.Add(new MDP_Rect(m4, mm, m3, r.C4));
}
oldRect.Clear();
oldRect = new List<MDP_Rect>(newRect);
newRect.Clear();
h /= 2;
}
List<MDP_Rect> sorted = new List<MDP_Rect>();
sorted = oldRect.OrderBy(y => y.C1.y).ThenBy(x => x.C1.x).ToList();
List<MDP_Point> mapArray = new List<MDP_Point>();
mapArray.AddRange(CreateArray(sorted));
CreateImage(size, mapArray, rg);
}
MDP_Point only contains x, y and z values
MDP_Rectangle contains 4 points, creating a rectangle
The CreateArray() method only takes the ordered rectangle list and outputs and list of points in the correct order to create an image.
CreateArray():
private List<MDP_Point> CreateArray(List<MDP_Rect> lRect)
{
List<MDP_Point> p = new List<MDP_Point>();
int size = (int)Math.Sqrt(lRect.Count);
int i = 0;
foreach (MDP_Rect r in lRect)
{
p.Add(new MDP_Point((int)r.C1.x, (int)r.C1.y, (int)r.C1.z));
if (i > 0 && i % size == size - 1)
{
p.Add(new MDP_Point((int)r.C2.x, (int)r.C2.y, (int)r.C2.z));
}
i++;
}
for (int a = 0; a < size; a++)
{
p.Add(new MDP_Point((int)lRect[(size * size - size) + a].C4.x,
(int)lRect[(size * size - size) + a].C4.y,
(int)lRect[(size * size - size) + a].C4.z));
if (a > 0 && a % size == size - 1)
{
p.Add(new MDP_Point((int)lRect[(size * size - size) + a].C3.x,
(int)lRect[(size * size - size) + a].C3.y,
(int)lRect[(size * size - size) + a].C3.z));
}
}
return p;
}
This is the method to create the image:
private void CreateImage(int size, List<MDP_Point> arr, double roughness)
{
Bitmap map = new Bitmap(size, size);
int ver = 0;
for (int i = 0; i < map.Height; i++)
{
for (int n = 0; n < map.Width; n++ )
{
int h = (int)arr[ver].z + 127;
if (h < 0)
{
h = 0;
}
else if (h > 255)
{
h = 255 ;
}
Color c = Color.FromArgb(h, h, h);
//map.SetPixel(n, i, c);
map.SetPixel(i, n, c);
ver++;
}
}
Bitmap m = new Bitmap(map);
bool saved = true;
int num = 0;
while (saved)
{
if (File.Exists("map_S" + size + "_R" + roughness + "_" + num + ".png"))
{
num++;
}
else
{
m.Save("map_S" + size + "_R" + roughness + "_" + num + ".png", System.Drawing.Imaging.ImageFormat.Png);
saved = false;
}
}
map.Dispose();
m.Dispose();
}
The fact that any value below 0 is set to 0 and any value above 255 is set to 255 is probably a big issue.... not sure what to do about it.
Here's an image generated by the code:
Size: 1024
Roughness: 0.5
The most obvious issues are the diagonal "ridge lines" and the tiled look there is.
At this point, i'm not sure what to do to fix this to make it look more natural.
Any ideas?
Here, I think part of the problem is your hacking of the h variable with 255 and 0. I tried the code using:
int h = (int) arr[ver].z;
if (h < 0)
{
h = Math.Abs(h);
}
while(h > 255)
{
h -= 255;
}
On my PC the result was:
and when I used:
int h = (int) arr[ver].z + 127;
Note that I just had to create a testing MDP_Point class and MDP_Rect to test this...
To avoid these artifacts, you should use the two-stage method proposed by Peitgen et al. in "The Science of Fractal Images". They also suggest adding additional random displacements to all vertices after each subdivision step. I found a scanned excerpt here (page 45):
http://cs455.cs.byu.edu/lectureslides/FractalsPart2.pdf

Categories

Resources