Align labels in DataVisualization.Charting effectively - c#

I need to develop a chart using datavisualization. Now the chart looks like
below
In the above chart i am using rangebar to show min and max values, in rangebar the label (65---210) now comes in the middle part. But i need to show the min and max like one in red. ie min value in the start position of the rangebar and max value in the end position of the rangebar.
Please let me know if there is any way to do it

The way to do it is by handling the chart's Paint event.
You would need to do some more sophisticated calculations using the Graphics object to make it work for the generic case. But it should get you started.
public partial class WebForm1 : System.Web.UI.Page
{
float deltax, deltay, deltay2;
Font font;
Brush brush;
Random r;
protected void Page_Load(object sender, EventArgs e)
{
deltax = 7.5F;
deltay = 60;
deltay2 = 5;
font = new Font("Courier", 14);
brush = new SolidBrush(Color.Red);
r = new Random();
for (int i = 1; i <= 5; i++)
Chart1.Series[0].Points.Add(new DataPoint(i, new double[2] { r.Next(10, 40), r.Next(60, 90) }));
}
protected void Chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
if (e.ChartElement.ToString().Contains("Series"))
{
int count = Chart1.Series[0].Points.Count - 1;
for (int i = count; i >= 0; i--)
{
DataPoint dp = Chart1.Series[0].Points[i];
float size = (float)(deltax*(dp.YValues[1] - dp.YValues[0] + deltay2));
float x = (float)(deltax * dp.YValues[0]);
float y = (float)(deltay * (count - dp.XValue + 2));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[0]), font, brush, new PointF(x, y));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[1]), font, brush, new PointF(x + size, y));
}
}
}
}

Related

Set static space between custom axes

I have to have static space (lets say 20 px) between axes.
If I have more axes on the left, it is possible to set their StartPosition and EndPosition in pixels or in percents.
For pixels setting - is there some way, how I can get the height of the space, where are the axes (red line in the picture)?
For percents setting - is there some way, how I can automatically convert 20 px to percents? I could calculate that by myself if I know the height, but I don't know how to get it - see 1.
I am able to get the height of the whole panel, where the chart is, but I don't know where to get the actual height of the space for left axes.
tChart1.Chart.ChartRect gives you the Rectangle of the "drawing zone". In your case, where you have to get that size before the axes calculations, you can use GetAxesChartRect event and use e.AxesChartRect as follows:
private void testChartRect()
{
for (int i = 0; i < 4; i++)
{
Line line = new Line(tChart1.Chart);
tChart1.Series.Add(line);
line.Chart = tChart1.Chart;
line.FillSampleValues();
Axis axis = new Axis();
tChart1.Axes.Custom.Add(axis);
line.CustomVertAxis = axis;
axis.AxisPen.Color = line.Color;
axis.Labels.Font.Color = line.Color;
}
tChart1.Aspect.View3D = false;
tChart1.Panel.MarginLeft = 10;
//tChart1.AfterDraw += TChart1_AfterDraw1;
tChart1.GetAxesChartRect += TChart1_GetAxesChartRect;
}
private void TChart1_GetAxesChartRect(object sender, GetAxesChartRectEventArgs e)
{
Rectangle chartRect = e.AxesChartRect;
int axisLength = (chartRect.Bottom - chartRect.Top) / tChart1.Axes.Custom.Count;
int margin = 20;
for (int i = 0; i < tChart1.Axes.Custom.Count; i++)
{
Axis axis = tChart1.Axes.Custom[i];
axis.StartEndPositionUnits = PositionUnits.Pixels;
axis.StartPosition = i * axisLength;
axis.EndPosition = (i + 1) * axisLength - (i != (tChart1.Axes.Custom.Count - 1) ? margin : 0);
}
}
private void TChart1_AfterDraw1(object sender, Graphics3D g)
{
tChart1.Graphics3D.Brush.Color = Color.Red;
tChart1.Graphics3D.Brush.Transparency = 80;
tChart1.Graphics3D.Rectangle(tChart1.Chart.ChartRect);
}

Initiate panel with drawings

I am now drawing to a panel some dots to indicate a sort of dotted grid with 1% of margin of total panel width.
This is what I am doing now:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Pen my_pen = new Pen(Color.Gray);
int x,y;
int k = 1 ,t = 1;
int onePercentWidth = panel1.Width / 100;
for (y = onePercentWidth; y < panel1.Height-1; y += onePercentWidth)
{
for (x = onePercentWidth; x < panel1.Width-1; x += onePercentWidth)
{
e.Graphics.DrawEllipse(my_pen, x, y, 1, 1);
}
}
}
What is bothering me is that when the app starts I can see the dots being drawn on the panel. Even if it is very quick it still bothers me a lot.
Is it possible to draw the dots on the panel and load it directly drawn?
Thank you for the help
You could create a bitmap and draw it instead.
But before you do that: DrawEllipse is a little expensive. Use DrawLine with a Pen that has a dotted linestyle instead:
int onePercentWidth = panel1.ClientSize.Width / 100;
using (Pen my_pen = new Pen(Color.Gray, 1f))
{
my_pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
my_pen.DashPattern = new float[] { 1F, onePercentWidth -1 };
for (int y = onePercentWidth; y < panel1.ClientSize.Height - 1; y += onePercentWidth)
e.Graphics.DrawLine(my_pen, 0, y, panel1.ClientSize.Width, y);
}
Note that I am using using so I don't leak the Pen and ClientSize so I use only the inner width. Also note the exaplanation about the custom DashPattern on MSDN

Mandelbrot Conversion [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm receiving no errors but when I'm running it I'm also unable to see the Mandelbrot it just displays the grey box, I'm currently stuck at this one point thanks for any help, if you see any other parts of my code which contains grammar or coding errors it would be much appreciated if you told me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace SE_Fractal_Assignment
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public struct HSBColor
{
float h;
float s;
float b;
int a;
public HSBColor(float h, float s, float b)
{
this.a = 0xff;
this.h = Math.Min(Math.Max(h, 0), 255);
this.s = Math.Min(Math.Max(h, 0), 255);
this.b = Math.Min(Math.Max(h, 0), 255);
}
public float H
{
get { return h; }
}
public float S
{
get { return s; }
}
public float B
{
get { return b; }
}
public int A
{
get { return a; }
}
public Color Color
{
get
{
return FromHSB(this);
}
}
public static Color FromHSB(HSBColor hsbColor)
{
float r = hsbColor.b;
float g = hsbColor.b;
float b = hsbColor.b;
if (hsbColor.s != 0)
{
float max = hsbColor.b;
float dif = hsbColor.b * hsbColor.s / 255f;
float min = hsbColor.b - dif;
float h = hsbColor.h * 360f / 255f;
if (h < 60f)
{
r = max;
g = h * dif / 60f + min;
b = min;
}
else if (h < 120f)
{
r = -(h - 120f) * dif / 60f + min;
g = max;
b = min;
}
else if (h < 180f)
{
r = min;
g = max;
b = -(h - 120f) * dif / 60f + min;
}
else if (h < 240f)
{
r = min;
g = -(h - 240f) * dif / 60f + min;
b = max;
}
else if (h < 300f)
{
r = -(h - 240f) * dif / 60f + min;
g = min;
b = max;
}
else if (h <= 360f)
{
r = max;
g = min;
b = -(h - 360f) * dif / 60f + min;
}
else
{
r = 0;
g = 0;
b = 0;
}
}
return Color.FromArgb
(
hsbColor.a,
(int)Math.Round(Math.Min(Math.Max(r, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(g, 0), 255)),
(int)Math.Round(Math.Min(Math.Max(b, 0), 255))
);
}
}
private const int MAX = 256; // max iterations
private const double SX = -2.025; // start value goal
private const double SY = -1.125; // start value imaginary
private const double EX = 0.6; // end value real
private const double EY = 1.125; // end value imaginary
private static int x1, y1, xs, ys, xe, ye;
private static double xstart, ystart, xende, yende, xzoom, yzoom;
private static bool action, rectangle, finished;
private static float xy;
//private Image picture1;
private System.Drawing.Bitmap bitmap;
private Graphics g1;
private Cursor c1, c2;
private HSBColor HSBcol = new HSBColor();
// private HSB HSBcol = new HSB();
private void Form1_Paint(object sender, PaintEventArgs e)
{
g1 = e.Graphics;
g1.DrawImage(bitmap, 0, 0, x1, y1);
g1.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
init();
start();
}
public void init()
{
//HSBcol = new HSB();
finished = false;
c1 = Cursors.WaitCursor;
c2 = Cursors.Cross;
x1 = 640;
y1 = 480;
xy = (float)x1 / (float)y1;
bitmap.SetPixel(x1, y1, Color.Blue);
g1 = Graphics.FromImage(bitmap);
finished = true;
// xy = (float)x1 / (float)y1;
//picture = createImage(x1, y1);
//g1 = picture.getGraphics();
}
public void destroy() // delete all instances
{
if (finished)
{
//removeMouseListener(this);
//removeMouseMotionListener(this);
//bitmap = null;
g1 = null;
c1 = null;
c2 = null;
//System.gc(); // garbage collection
GC.Collect();
}
}
public void start()
{
action = false;
rectangle = false;
initvalues();
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
mandelbrot();
}
public void stop()
{
}
public void paint(Graphics g)
{
update(g);
}
public void update(Graphics g)
{
/* Pen myPen = new Pen(Color.White);
g.DrawImage(bitmap, 0, 0);
if (rectangle)
{
if (xs < xe)
{
if (ys < ye)
{
g.DrawRectangle(myPen, xs, ys, (xe - xs), (ye - ys));
}
}
else
{
g.DrawRectangle(myPen, xs, ys, (xe - xs), (ye - ys));
}
myPen.Dispose();
}*/
}
private void mandelbrot() // calculate all points
{
int x, y;
float h, b, alt = 0.0f;
action = false;
for (x = 0; x < x1; x += 2)
for (y = 0; y < y1; y++)
{
h = pointcolour(xstart + xzoom * (double)x, ystart + yzoom * (double)y);
// color value
if (h != alt)
{
b = 1.0f - h * h; // brightnes
///djm added
///HSBcol.fromHSB(h,0.8f,b);
///
//convert hsb to rgb then make a Java Color
Color color = HSBColor.FromHSB(new HSBColor(h * 255, 0.8f * 255, b * 255));
///g1.setColor(col);
//djm end
//djm added to convert to RGB from HSB
//g1.setColor(Color.getHSBColor(h, 0.8f, b));
//djm test
// Color col = Color.FromArgb(0, 0, 0, 0);
//red = Color.Red;
// green = Color.Green;
// blue = Color.Blue;
//djm
alt = h;
}
Pen pen = new Pen(Color.Aqua);
g1.DrawLine(pen, x, y, x + 1, y);
}
//showStatus("Mandelbrot-Set ready - please select zoom area with pressed mouse.");
//setCursor(c2);
action = true;
}
private float pointcolour(double xwert, double ywert)
// color value from 0.0 to 1.0 by iterations
{
double r = 0.0, i = 0.0, m = 0.0;
int j = 0;
while ((j < MAX) && (m < 4.0))
{
j++;
m = r * r - i * i;
i = 2.0 * r * i + ywert;
r = m + xwert;
}
return (float)j / (float)MAX;
}
private void initvalues() // reset start values
{
xstart = SX;
ystart = SY;
xende = EX;
yende = EY;
if ((float)((xende - xstart) / (yende - ystart)) != xy)
xstart = xende - (yende - ystart) * (double)xy;
}
private void Form1_paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g1 = g;
action = false;
rectangle = false;
initvalues();
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
//picture = g.DrawImage;
//g.DrawImage(picture,0,0);
update(g);
mandelbrot();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (action)
{
xs = e.X;
ys = e.Y;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
// e.consume();
if (action)
{
xe = e.X;
ye = e.Y;
rectangle = true;
//repaint();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
rectangle = false;
}
private void Form1_Click(object sender, MouseEventArgs e)
{
}
public String getAppletInfo()
{
return "fractal.class - Mandelbrot Set a Java Applet by Eckhard Roessel 2000-2001";
}
}
}
Honestly, the code is so cluttered and disorganized, it's hard to know all of what might be wrong with it. Sorry to be so blunt.
That said, a couple of obvious problems I see involving your "g1" Graphics instance member.
First, you are using the same field for two purposes: when computing the original image, you expect this to be a Graphics instance you can use to draw into your bitmap. But in the Paint event, you set it to the Graphics instance for the window, into which the painting should be done.
Second, in that Paint event, you dispose the Graphics instance before you return. But the instance you're disposing isn't yours. It belongs to the Forms system, and the only thing you should be doing with it is drawing into it.
There actually appear to be two different Paint event handlers and it's not clear which one you're using. You only dispose the Graphics instance in one of those places, so that may or may not be the real problem.
Personally, I would break the problem down into different elements. For a relative novice, it can be hard enough just to correctly draw a bitmap. It can also be difficult to really grasp how Paint event handling should be done. And of course, there's the Mandelbrot computations themselves. Trying to implement all three things (and more) at the same time can be overwhelming, and will take a lot longer assuming you can figure it out at all.
I would start by writing a simple program that just has a single PictureBox, which when you click a button, your program creates a new Bitmap object, into which you draw something simple (say, a rectangle, circle, or maybe just some text) and then assigns that Bitmap object to the PictureBox.Image property.
Once you have that working, then you can change the drawing part of the code to draw a Mandelbrot image instead.
Finally, once you have that working, then you can work on using the Paint event to draw the bitmap into your window directly instead of using the PictureBox control (the main reason for wanting to do this would presumably be that you eventually want to update the image as it's being drawn...if you only want to show it at the very end, then IMHO the PictureBox is a better approach).

Moving picturebox graphic with interval

I'm creating graphic at picturebox from left to right side, by adding single pixel columns, with predetermined time intervals(300ms). When subsequent pixel columns exceed the picturebox width, I can't see more of them.
How to make moving picturebox window, which would allow to see the current pixel column all the time?
I'm using BASS library, code is below.
private void timer1_Tick_1(object sender, EventArgs e)
{
graphic = pictureBox1.CreateGraphics();
bool spectrum3DVoicePrint = visuals.CreateSpectrum3DVoicePrint(rHandle, graphic, pictureBox1.Bounds, Color.Navy, Color.Navy, pos, false, true);`
graphic.Dispose();
pos = ++;
}
you need to store each position in array.
Here is my simple code for demonstrate to draw line and move after reaches at width of picturebox. Make sure any mistake of any value of pixel,x,y,etc.. leads to wrong output.
int x = -1;
int y = 50;
Random rnd = new Random();
bool check = true;
int[,] pos;
int index = -1;
private void Form1_Load(object sender, EventArgs e)
{
//Initalize array
pos = new int[pictureBox1.Width + 2, 2];
}
private void timer1_Tick(object sender, EventArgs e)
{
Graphics graphic = pictureBox1.CreateGraphics();
if (x < pictureBox1.Width)
{
index++;
x++;
}
else
{
graphic.Clear(Color.Black);
for (int i = 0; i < pictureBox1.Width; i++)
{
pos[i, 1] = pos[i + 1, 1];
graphic.DrawRectangle(System.Drawing.Pens.Lime, pos[i, 0], pos[i, 1], 1, 1);
}
}
graphic.DrawRectangle(System.Drawing.Pens.Lime, x, y, 1, 1);
pos[index, 0] = x;
pos[index, 1] = y;
graphic.Dispose();
//for random dots
//y = rnd.Next(5, 95);
//for line
if (check)
y++;
else
y--;
if (y == 100)
check = false;
if (y == 5)
check = true;
}

Increase bar chart values with button clicks

I am trying to create a graph that will show the progress of a workout. Every five button clicks a tick should be added to the graph. This is a example of how it should look.
For demonstration purposes I am using a button click, In production the clicks will be every twenty revolutions of a wheel.
private int counter = 0;
private void button1_Click(object sender, EventArgs e)
{
counter++;
// code will go here
}
Thanks in advance
You can use either a Bitmap Buffer or a panel to draw on. Here is a headstart: Just a sample.
reference.
This solution is based on WinForms & Panel_Paint(). You may try to add vertical Progress Label and Chart's Y Axis value labeling.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1(){
InitializeComponent();
}
private int counter = 0;
private int px = 10;
private int py = 180;
private int total5Clicks = 0;
private void button1_Click(object sender, EventArgs e)
{
counter++;
label1.Text = "Total Clicks = " + counter.ToString();
if (Math.Abs(counter % 5) == 0){
if (Math.Abs(counter / 5) > 0){
total5Clicks = total5Clicks + 1;
PaintOnChartPanel(total5Clicks);}
}
}
private void panel1_Paint(object sender, PaintEventArgs e){
}
private void PaintOnChartPanel(int total5Times)
{
//Add a new Panel Paint EventHandler
panel1.Paint += new PaintEventHandler(panel1_Paint);
using (Graphics g = this.panel1.CreateGraphics())
{
Brush brush = new SolidBrush(Color.Green);
g.FillRectangle(brush, px, py, 20, 20);
Pen pen = new Pen(new SolidBrush(Color.White));
g.DrawRectangle(pen, px, py, 20, 20);
//add each total5Click into chart block
g.DrawString((total5Times).ToString(), new Font("Arial", 7),
new SolidBrush(Color.AntiqueWhite),
px + 1, py+8, StringFormat.GenericDefault);
pen.Dispose();}
if (py > 20){
py = py - 20;}
else{
MessageBox.Show("Reached Top of the Panel");
if (px < 200){
px = px + 20;
py = 180;}
else{
MessageBox.Show("Reached Right of the Panel");
}
}
}
}
}
Output Form:
You can determine if you have a multiple of five with
bool drawTickMark = clicks % 5 == 0;
% is the modulo operator which returns the remainder of an integer division. E.g. 13 % 5 = 3 and 13 / 5 = 2 because 2 * 5 + 3 = 13.
clicks % 5 will be zero for clicks = 0, 5, 10, 15, ...
I'm not much of an ASP.NET guy but here's an algorithm you can use to draw the squares
int perColumn = Height / squareSize;
int totalColumns = (squareCount / perColumn) + 1;
for (int y = 0; y <= totalColumns - 1; y++)
{
int itemCount = squareCount - (y * perColumn);
if (itemCount > perColumn)
itemCount = perColumn;
for (int x = 0; x <= itemCount - 1; x++)
e.Graphics.FillRectangle(RandomBrush, New Rectangle((column * SquareSize) + 3, (i * SquareSize) + 3, SquareSize - 2, SquareSize - 2))
public sealed class ClickGraph : Control
{
private int squareCount = 1;
public int SquareCount
{
get
{
return squareCount;
}
set
{
squareCount = value;
Invalidate();
}
}
private int squareSize = 25;
public int SquareSize
{
get
{
return squareSize;
}
set
{
squareSize = value;
Invalidate();
}
}
public ClickGraph()
{
SetStyle(ControlStyles.ResizeRedraw, true);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(BackColor);
int perColumn = Height / squareSize;
int totalColumns = (squareCount / perColumn) + 1;
for (int y = 0; y <= totalColumns - 1; y++)
{
int itemCount = squareCount - (y * perColumn);
if (itemCount > perColumn)
itemCount = perColumn;
for (int x = 0; x <= itemCount - 1; x++)
e.Graphics.FillRectangle(RandomBrush, New Rectangle((column * SquareSize) + 3, (i * SquareSize) + 3, SquareSize - 2, SquareSize - 2))
}
}
}

Categories