i'm working with C# chart class to display a curve. the type of the series is spline.
the thing would i do is show a crosshair cursor in the chart area. the vertical line of this cursor should move with the mouse when the mouse enter the chart. but the horizontal line should move whit the curve line not with mouse movement.
the code which i typed is here:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
Point mousePoint = new Point(e.X, e.Y);
chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(mousePoint,false);
chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(mousePoint,false);
}
this code cause the cursor move whith the mouse and the result is like in this image:
to make the horizontal line of the cursor follow the curve line which is a sinusoidal signal here. i should know the Point of intersection between the vertical line of the cursor and the curve line. as this picture show:
is there any direct way to find this point? any help plz!.
You can get the y pixel-offset relative to the top of the chart area if you know the following:
height = Chart height in pixels
rangeMin/rangeMax = Chart range min/max (here -150/150)
value = function value (bottom image, approx. 75)
Taking the following formula:
yOffset = height * (rangeMax - value) / (rangeMax - rangeMin);
You should be able to plug yOffset into your MouseMove function like so:
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
double yOffset = GetYOffset(chart1, e.X);
Point mousePoint = new Point(e.X, yOffset);
chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(mousePoint,false);
chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(mousePoint,false);
}
// ChartClass chart is just whatever chart you're using
// x is used here I'm assuming to find f(x), your value
private double GetYOffset(ChartClass chart, double x)
{
double yOffset;
// yOffset = height * (rangeMax - value) / (rangeMax - rangeMin);
return yOffset;
}
In this function I get the position of cursor X with the method GetXOfCursor();
after that I take the series point with this statement:
points = _theChart.Series[i].Points;
After with the last if statement I see the point that matches with the position X of the cursor
and I calculate the mean value of Y of this 2 Point because the point intercepted with the cursor is an interpolation line made by the windows chart control
public string GetPointInterceptedCursorX()
{
string values = string.Empty;
// Far uscire le etichette ai punti intercettati
var xPosCursor = GetXOfCursor();
DataPointCollection points = null;
for (int i = 0; i < _theChart.Series.Count; i++)
{
if (_theChart.Series[i].BorderWidth == ChartConst.THICKNESS_LINE_ENABLED)
{
points = _theChart.Series[i].Points;
break;
}
}
if (points == null) return "No Curve Selected";
for (int i = 0; i < points.Count - 1; i++)
{
if ((xPosCursor > points[i].XValue & xPosCursor < points[i + 1].XValue) | xPosCursor > points[i + 1].XValue & xPosCursor < points[i].XValue)
{
var Yval = (points[i].YValues[0] + points[i + 1].YValues[0]) / 2;
values += $"Y= {Yval} {Environment.NewLine}";
}
}
values += "X=" + " " + String.Format("{0:0.00}", xPosCursor);
return values;
}
Related
I have a working mouse click event on my windows form graph and now I'd like to add data points on each click to make it visible where on the graph it was clicked. Upon the 3rd click, the previous 2 will clear and the 3rd and 4th click will have their own new data points and so on and so on (2 data points at a time to show start and stop locations and the difference/delta is calculated between those to positions).
My current code looks like:
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
HitTestResult result = chart1.HitTest(e.X, e.Y);
if (result.PointIndex >= 0)
{
if (diffCounter == 0)
{
xOne = result.Series.Points[result.PointIndex].YValues[0];
diffCounter++;
//Console.WriteLine("VALY " + xOne);
}
else if (diffCounter == 1)
{
xTwo = result.Series.Points[result.PointIndex].YValues[0];
diffCounter = 0;
//Console.WriteLine("Delta = " + Math.Round(Math.Abs(xTwo - xOne)), 2);
pointDifferenceTextBox.Text = Math.Round((Math.Abs(xTwo - xOne)), 2).ToString();
}
}
}
I cannot find anything anywhere about adding a data point based on where a hit test was performed on a line chart (or any chart for that matter).
Difference Counter is just an int to determine whether its the first or second click.
xOne is to get the first click y-value, xTwo is to get the second click y-value.
EDIT: I'd like to had a circle data point based on where the hit test is performed on.
Since the post was changed a new answer seems warranted.
Here is how one can create two points to be drawn in a Paint event.
First we need to store them:
PointF p1 = PointNull;
PointF p2 = PointNull;
To flag state we also use a static value:
static PointF PointNull = new PointF(-123f, -123f);
You could use some other flag as well in order to control switching between the 1st and 2nd point.
Next we need to store values in the click :
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
Axis ax = chart1.ChartAreas[0].AxisX;
Axis ay = chart1.ChartAreas[0].AxisY;
double x = ax.PixelPositionToValue(e.X);
double y = ay.PixelPositionToValue(e.Y);
y = GetMedianYValue(chart1.Series[0], x);
if (p1 == PointNull ||(p1 != PointNull && p2 != PointNull))
{
p1 = new PointF((float)x, (float)y);
p2 = PointNull;
}
else
{
p2 = new PointF((float)x, (float)y);
}
// values have changed, trigger drawing them!
chart1.Invalidate();
}
Note that I first use the axis functions to get the axis values of the clicked position. Then I overwrite the y-value by a function that calculates the point on the line..:
double GetMedianYValue(Series s, double xval )
{
// Findclosest datapoints:
DataPoint dp1 = s.Points.Where(x => x.XValue <= xval).LastOrDefault();
DataPoint dp2 = s.Points.Where(x => x.XValue >= xval).FirstOrDefault();
// optional
dp1.MarkerStyle = MarkerStyle.Circle;
dp1.MarkerColor = Color.Purple;
dp2.MarkerStyle = MarkerStyle.Circle;
dp2.MarkerColor = Color.Violet;
double dx = dp2.XValue - dp1.XValue;
double dy = dp2.YValues[0] - dp1.YValues[0];
// same point
if (dx == 0) return dp1.YValues[0];
// calculate median
double d = dp1.YValues[0] + dy / dx * ( xval - dp1.XValue) ;
return d;
}
Note that this function marks the neighbouring datapoints for testing only!
Finally we need to draw the two points:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Axis ax = chart1.ChartAreas[0].AxisX;
Axis ay = chart1.ChartAreas[0].AxisY;
int x1 = (int)ax.ValueToPixelPosition(p1.X);
int y1 = (int)ay.ValueToPixelPosition(p1.Y);
int x2 = (int)ax.ValueToPixelPosition(p2.X);
int y2 = (int)ay.ValueToPixelPosition(p2.Y);
if (x1 >= 0 && x1 < chart1.Width) // sanity check
if (p1 != PointNull)
e.ChartGraphics.Graphics.DrawEllipse(Pens.LightSeaGreen, x1 - 3, y1 - 3, 6, 6);
if (x2 >= 0 && x2 < chart1.Width) // sanity check
if (p2 != PointNull)
e.ChartGraphics.Graphics.DrawEllipse(Pens.Red, x2 - 3, y2 - 3, 6, 6);
}
Here is the result:
The original post asked for adding a DataPoint at the clicked location. For this HitTest is not useful.
Instead you need one of the the axis functions; PixelPositionToValue will convert the pixels position to an axis value..:
Axis ax = chart1.ChartAreas[0].AxisX;
Axis ay = chart1.ChartAreas[0].AxisY;
double x = ax.PixelPositionToValue(e.X);
double y = ay.PixelPositionToValue(e.Y);
DataPoint dp = new DataPoint(x, y);
dp.Color = Color.Red;
chart1.Series[0].Points.Add(dp);
Note that these function are only valid in either one of the paint or one of the mouse events!
I have made an object class and set the mouseEnter event on it. Object describes a process of creating a circle using opengl (here is drawing process function):
public void DrawCicrle()
{
GL.Begin(PrimitiveType.TriangleFan);
GL.Color4(Color_);
GL.Vertex2(X_, Y_);
for (int i = 0; i < 360; i++)
{
GL.Vertex2(X_ + Math.Cos(i) * Radius_, Y_ + Math.Sin(i) * Radius_);
}
GL.End();
}
Then I did a mouseEvent, but cant get the coordinates of cursor correctly. What are the correct conditions to get points in the arc of a circle?
This function returns a points, but with a little offset on the left side (X_ and Y_ are the center of a circle (double type) Radius_ is double type too):
public Point CursorLocation
{
get
{
return CursorLocation_;
}
set
{
this.CursorLocation_ = value;
for (int i = 0; i < 360; i++)
{
if (CursorLocation_.X <= X_ + Math.Cos(i) * Radius_ && CursorLocation_.Y<= Y_ + Math.Sin(i) * Radius_ && CursorLocation_.Y>=Y_-Radius_)
{
Enter(new Point(CursorLocation_.X, CursorLocation_.Y));
break;
}
}
}
}
The condition is dx * dx + dy * dy < R * R, where dx=Math.Abs(x-cx) and dy=Math.Abs(y-cy)
(x,y) is the cursor location and (cx,cy) the circle center
So you check the Euclidian distance between circle Center and some Point. To avoid square root calculation you just square both sides of comparison
Use <= if you also want to count-in the circle border
I am developing a C# win form GUI for controlling a two-motor XY stage. I have drawn a 100 x 100 square grid pattern on a picturebox in which each square, when clicked, represents a coordinate that the two motors must move to. I have studied this link
PictureBox Grid and selecting individual cells when clicked on and this PictureBox- Grids and Filling in squares (Game of Life) for drawing a grid and marking the clicked positions.
Now I have to transform the series of randomly clicked points to actual movement of the two motors.
How shall I translate the click coordinates programmatically to give commands to control the motors?
I know how to move and control the motors without referring to the screen coordinates, i.e. by using eyes.
Thank you very much for your kind help.
Update1:
Hello... I think I am thinking too much in a confusing way to move the motors from one point to another despite Sebastien's great help. I wanted to try some logic below but I appreciate if somebody can enlighten me how best to implement this.
private void pictureBoxGrid_MouseClick(object sender, MouseEventArgs e)
{
//int x = e.X;
int x = cellSize * (e.X / cellSize);
int y = cellSize * (e.Y / cellSize);
int i = x / 8; // To limit the value to below 100
int j = y / 8;
// Reverse the value of fill_in[i, j] - if it was false, change to true,
// and if true change to false
fill_in[i, j] = !fill_in[i, j];
if (fill_in[i, j])
{
//Save the coordinate in a list
filledSq.Add(new Point(i, j));
using (Graphics g = Graphics.FromImage(buffer))
{
g.FillRectangle(Brushes.Black, x + 1, y + 1, 7, 7);
}
}
else
{
//Delete the coordinate in a list
filledSq.Remove(new Point(i, j));
Color customColor = SystemColors.ControlLightLight;
using (Graphics g = Graphics.FromImage(buffer))
using (SolidBrush shadowBrush = new SolidBrush(customColor))
{
g.FillRectangle(shadowBrush, x + 1, y + 1, 7, 7);
}
}
//pictureBoxGrid.BackgroundImage = buffer;
pictureBoxGrid.Invalidate();
}
private void buttonSavePoints_Click(object sender, EventArgs e)
{
// to be implemented...
}
private void buttonRun_Click(object sender, EventArgs e)
{
var noOfDots = filledSq.Count;
filledSq = filledSq.OrderBy(p => p.X).ThenBy(p => p.Y).ToList();
var motor = new Motor();
for (var i = 0; i < noOfDots; i++)
{
motor.Move(filledSq[i].X, filledSq[i].Y); //call the motor to move to X,Y here?
//do sth at each position
}
}
Since you wrote, that you know how to move the motors programmatically this answer will be more theoretical:
Each steppermotor has a predefined anglewidth per step (e.g. 1.8°).
And if you know where your Motors are (for example at a predefined starting point with limitswitches (0|0)) you can calculate where they need to be.
For the precision there are multiple factors like if you are using Belts or threaded rods.
An examplemethod could look like this:
private static float stepwidth = 1.8;
private static beltConverionPerDegree = 0.2; // Or rod
private float currentPositionX = 0;
private float currentPositionY = 0;
public Tuple<int, int> GetSteps(float x, float y) {
// calculate the position relative to the actual position (Vector between two points)
float relativeX = x - currentPositionX;
float relativeY = y - currentPositionY;
return new Tuple<int, int> (relativeX / (stepwidth * beltConverionPerDegree), relativeY / (stepwidth * beltConverionPerDegree));
}
beltConverionPerDegree means how much distance your motor moves the belt for each degree.
What i want is to set borders between two series in StackedBar Like this image The bold black line between blue and green
I can not figure out any idea to specify the border, i tried to set the borders to the series throuh this code
chart.Series["series0"].BorderWidth = 2;
chart.Series["series0"].BorderColor = Color.Black;
chart.Series["series0"].BorderDashStyle = ChartDashStyle.Solid;
but this the result i got
Here's my code
double l = Convert.ToDouble(query1[i - 1][0]) - 10;
string n = query1[i - 1][1];
int count = 0;
for (double t = l; t < l + 10; t++)
{
//Next line Calc. the occurence of character in a text file
count = n.Split('C').Length - 1;
//Multiple the occurence by 10 so it become percent
chart.Series["series0"].Points.AddXY(t, count * 10);
chart.Series["series0"]["PointWidth"] = "1";
chart.Series["series0"].BorderWidth = 2;
chart.Series["series0"].BorderColor = Color.Black;
chart.Series["series0"].BorderDashStyle = ChartDashStyle.Solid;
count = n.Split('o').Length - 1;
chart.Series["series1"].Points.AddXY(t, count * 10);
chart.Series["series1"]["PointWidth"] = "1";
}
How to achieve the first pic effect using StackedBar ? , if i can not using StackedBar, what chart type you suggest to use ??
There are no built-in chart elements that could easily be made into a borderline between those two Series. (Creating LineAnnotations to achieve this would be a nightmare..)
So the way to add the lines is to draw them onto the surface of the Chart. This is most naturally done in the PostPaint event, provided just for such adornments.
Here the Axes have handy functions to convert between the data values and the pixel positions. We need the ValueToPixelPosition method.
I will take you through variations of Chart drawing that gradually get a little more complicated as we approach the final version..:
Let's start with a simple example: Let's build and adorn a StackedArea chart; here is the drawing code:
private void chart2_PostPaint(object sender, ChartPaintEventArgs e)
{
Series s = chart1.Series[0];
ChartArea ca = chart1.ChartAreas[0];
var pp = s.Points.Select(x=>
new PointF( (float)ca.AxisX.ValueToPixelPosition(x.XValue),
(float)ca.AxisY.ValueToPixelPosition(x.YValues[0]) ) );
if (s.Points.Count > 1)
using (Pen pen = new Pen(Color.DarkOliveGreen, 4f))
e.ChartGraphics.Graphics.DrawLines(pen, pp.ToArray());
}
The Points.Select is really just a shorthand for a loop; so after creating the pixel point list we simply draw it.
Now, as you can see, as StackedArea chart is pointy and doesn't look like a StackedBar or StackedColumn chart. So let's cheat and 'rectify' the area chart by adding a few extra points:
void rectifyArea(Series s)
{
for (int i = s.Points.Count - 1; i > 0; i--)
s.Points.InsertXY(i, i - 1, s.Points[i].YValues[0]);
}
Results:
Now that was not so hard; unfortunately you just can't turn a StackedArea to go from left to right instead of bottom-up. So we need to change the chart type to a Bar type eventually..
Here the challenge is to find the right upper and lower corners of those bars. We do have the DataPoint values, but these are in the middle of the bars. So we need to add/subtract half of the Bars' width to get the corners. For this we need the width.
While you have set it with the PointWidth property to 1, what we really need is the pixel width. We best get it by subtracting the pixel coordinates of two neighbouring points.
This makes the PostPaint event a little longer, but still not overly complicated; we will start with a StackedColumn chart, adding two corner points for each data point:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Series s = chart1.Series[0];
ChartArea ca = chart1.ChartAreas[0];
if (s.Points.Count <= 0) return;
// calculate width of a column:
int pp1 = (int)ca.AxisX.ValueToPixelPosition(s.Points[0].XValue);
int pp2 = (int)ca.AxisX.ValueToPixelPosition(s.Points[1].XValue);
float w2 = Math.Abs(pp2 - pp1) / 2f;
List<PointF> points = new List<PointF>();
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
points.Add(new PointF( (int)ca.AxisX.ValueToPixelPosition(dp.XValue) - w2,
(int)ca.AxisY.ValueToPixelPosition(dp.YValues[0]) ));
points.Add(new PointF( (int)ca.AxisX.ValueToPixelPosition(dp.XValue) + w2,
(int)ca.AxisY.ValueToPixelPosition(dp.YValues[0]) ));
}
if (points.Count > 1)
using (Pen pen = new Pen(Color.DarkOliveGreen, 4f))
e.ChartGraphics.Graphics.DrawLines(pen, points.ToArray());
}
Now this looks pretty much identical to our fake version of the 'rectified area chart'. What will we need to change to apply this to a StackedBar chart? Almost nothing! The only two things we need to take care of are
the direction of the y-axis. Since the points move upward but the pixel coordinates of GDI+ graphhics move downwards we need to create the two cornerpoints in the reverse order.
And we need to reverse the x- and y coodinates, as the axes are reversed for all types of Bar charts.
Here are the two stacked charts with a border:
This is the loop for the StackBar chart:
for (int i = 0; i < s.Points.Count; i++)
{
points.Add(new PointF( (float)ca.AxisY.ValueToPixelPosition(s.Points[i].YValues[0]),
(float)ca.AxisX.ValueToPixelPosition(s.Points[i].XValue) + w2));
points.Add(new PointF( (float)ca.AxisY.ValueToPixelPosition(s.Points[i].YValues[0]),
(float)ca.AxisX.ValueToPixelPosition(s.Points[i].XValue) - w2));
}
Note that I am drawing with a fixed pen width of 4 pixels. To make it scale with the Chart you may want to calculate the pen width dynamically..
Update
To draw borders on top of several series you can put the code into a loop like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = chart1;
Series s0 = chart.Series[0];
ChartArea ca = chart.ChartAreas[0];
// calculate width of a bar:
int pp1 = (int)ca.AxisX.ValueToPixelPosition(s0.Points[0].XValue);
int pp2 = (int)ca.AxisX.ValueToPixelPosition(s0.Points[1].XValue);
float delta = Math.Abs(pp2 - pp1) / 2f;
for (int s = 0; s < chart.Series.Count; s++)
{
List<PointF> points = new List<PointF>();
for (int p = 0; p < chart.Series[s].Points.Count; p++)
{
DataPoint dp = chart.Series[s].Points[p];
double v = GetStackTopValue(chart, s, p);
points.Add(new PointF((float)ca.AxisY.ValueToPixelPosition(v),
(float)ca.AxisX.ValueToPixelPosition(dp.XValue) + delta));
points.Add(new PointF((float)ca.AxisY.ValueToPixelPosition(v),
(float)ca.AxisX.ValueToPixelPosition(dp.XValue) - delta));
}
using (Pen pen = new Pen(Color.DarkOliveGreen, 3f))
e.ChartGraphics.Graphics.DrawLines(pen, points.ToArray());
}
}
double GetStackTopValue(Chart chart, int series, int point)
{
double v = 0;
for (int i = 0; i < series + 1; i++)
v += chart.Series[i].Points[point].YValues[0];
return v;
}
How can i simulate a spray like windows paint ? i think it create points random , what is your opinion?
Yes, I would say it colors random pixels within a certain radius of the selection point. There's also probably a time delay between the coloring of one pixel and the other, because machines today are fast enough to be able to color every possible pixel (As long as the radius is small) before you could let go of the mouse button.
Also, I think the algorithm that Paint uses can select a pixel to paint even if it already has been painted, since sometimes you can end up with a painted circle with a few unpainted pixels inside.
The pattern for spray paint would be semi-random. If you get out a can of Krylon and slowly spray a line on a wall, you end up with a wide solid line that fades out to the background with a gradient around the edges. Spray in one spot for ten seconds, and you get a big dot in the center in which the color is fully saturated, with a radial gradient to the background.
So- your variables for simulation include:
Time holding the "sprayer" (mouse button)
Motion of the "can" (mouse)
Speed of the "can" (fast moves make a light, unsaturated line. Slow moves make a thick, saturated line with a gradient)
spread pattern: is the spray focused like an airbrush, or big like a spray can?
"Distance": How far away is the "sprayer" from the "canvas"?
You have received a number of answers pointing you in the right direction to start handling the user experience of the spray effect. Based on your reponse to my comment you also need an algorithm for generating the random points within the radius.
There are a number of ways to do this, and probably the most obvious would be to use polar coordinates to select the random point and then transform the polar coordinate to a cartesian (x,y) coordinate to render the pixel. Here is a simple example of this approach. To keep things simple, I have just drawn a simple 1x1 ellipse for each point.
private Random _rnd = new Random();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int radius = 15;
using (Graphics g = this.CreateGraphics())
{
for (int i = 0; i < 100; ++i)
{
// Select random Polar coordinate
// where theta is a random angle between 0..2*PI
// and r is a random value between 0..radius
double theta = _rnd.NextDouble() * (Math.PI * 2);
double r = _rnd.NextDouble() * radius;
// Transform the polar coordinate to cartesian (x,y)
// and translate the center to the current mouse position
double x = e.X + Math.Cos(theta) * r;
double y = e.Y + Math.Sin(theta) * r;
g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1));
}
}
}
Alternatively, you can randomly select x,y coordinates from the rectangle that fits the spray circle and using the circle equation r^2 = x^2 + y^2 test the point to determine if it lies inside the circle, if it does you randomly select another point and test again until you have a point that lies within the circle. Here is a quick sample of this approach
private Random _rnd = new Random();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int radius = 15;
int radius2 = radius * 2;
using (Graphics g = this.CreateGraphics())
{
double x;
double y;
for (int i = 0; i < 100; ++i)
{
do
{
// Randomy select x,y so that
// x falls between -radius..radius
// y falls between -radius..radius
x = (_rnd.NextDouble() * radius2) - radius;
y = (_rnd.NextDouble() * radius2) - radius;
// If x^2 + y^2 > r2 the point is outside the circle
// and a new point needs to be selected
} while ((x*x + y*y) > (radius * radius));
// Translate the point so that the center is at the mouse
// position
x += e.X;
y += e.Y;
g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1));
}
}
}
You can create a spray pattern of various intensities by sampling some number (related to the desired intensity and spread) of polar coordinates. To do this, determine a random polar coordiate (ρ, θ) for each sample by:
ρ sampled from N(0, 1): Use a Normal (Gaussian) distribution for the distance from the exact center of your spray pattern. I don't recall if there's a normal variate generator in the .NET library. If there isn't, you can create one from a U(0, 1) generator.
θ sampled from U(0, π): Sample the angular component from the Uniform Continuous Distribution. Without loss of performance or generality, you could instead sample on U(nπ, mπ) for n < m, but U(0, π) will probably be fine for what you need.
The Cartesian coordinates of each sample are give by (Tx + Sxρ cos θ, Ty + Syρ sin θ) where (Tx, Ty) is the center of the spray pattern you want to create; Sx and Sy are the spread factors you want to have in the x and y directions respectively.
Try using the timer
public partial class Form1 : Form
{
int Radious = 5;
Random _rnd = new Random();
Timer T = new Timer();
int InterVal = 1000;
MouseEventArgs MEA = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
T.Tick += (O, E) =>
{
StartSpray();
};
this.MouseDown += (O, E) =>
{
MEA = E;
T.Interval = InterVal;
T.Start();
};
this.MouseUp += (O, E) =>
{
T.Stop();
};
}
private void StartSpray()
{
Point P = DrawPoint(Radious, MEA.X, MEA.Y);
// Draw the point on any graphics area you can add the color or anything else
}
private Point DrawPoint(int Radious, int StatX, int StartY)
{
double theta = _rnd.NextDouble() * (Math.PI * 2);
double r = _rnd.NextDouble() * Radious;
Point P = new Point { X = StatX + Convert.ToInt32(Math.Cos(theta) * r), Y = StartY + Convert.ToInt32(Math.Sin(theta) * r) };
return P;
}
}
please modify the Interval and the radius.
I think it's hard to find a sample on C#. Below I present a way to start your journey on this. Here I am using a texture brush.
private void Button1_Click(System.Object sender, System.EventArgs e)
{
try
{
Bitmap image1 = (Bitmap)Image.FromFile(#"C:\temp\mybrush.bmp", true);
TextureBrush t = new TextureBrush(image1);
t.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
Graphics formGraphics = this.CreateGraphics();
formGraphics.FillEllipse(t, new RectangleF(90.0F, 110.0F, 100, 100));
formGraphics.Dispose();
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show("Image file not found!");
}
}
as Jesse said, I think you should find an algorithm to spread random pixels.