Cannot create function char using Graphics c# - c#

I'm trying to plot the function y = x ^ 2 at a certain interval using the Graphics, but I can't. When I write start + = 1/10 (to increase the number of points) knocks out the error that the index went beyond the array, and in this case what it is now, the graph does not look as it should. Maybe someone can help me build this chart using Graphics.
P.S: yes I know I can use Chart, but the task is to do it through Graphics.
using System.Drawing;
using System.Windows.Forms;
namespace FormsForProgrammin
{
public partial class Form15 : Form
{
PointF[] p = new PointF[10];
int count = 0;
public Form15()
{
InitializeComponent();
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form15_Paint);
Calc();
}
private void Calc()
{
float start = float.Parse(textBox1.Text);
while(start<= float.Parse(textBox2.Text))
{
float res = start * start;
p[count] = new PointF(start, res);
count += 1;
start += 1;
}
}
private void Form15_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.TranslateTransform(150, 150);
e.Graphics.ScaleTransform(1, 0.25F);
e.Graphics.DrawLines(Pens.Blue, p);
}
}
}

you have an array of 10 points, and you are indexing them with the count variable. you have a couple of problems in that code:
you never reset count
you set start to the textBox1 value, and increment it by 1 untill it is over the textBox2 value. but this gap may be bigger than the number of points you have in the array
to solve for 1 you can either reset count once the loop is done, or simply define count in the Calc method itself (the latter would be the better option, since count is only relevant to the Calc method)
to solve for 2 you would need to calculate a step amount: the difference between values divided by the number of points,
use this step amount to make sure that the loop doesn't run more times than the numbers of points you have

Related

Mouse Drag - C# bot

First time doing this. I am currently building a bot using C# and want my bot to be able to move the mouse to a given point in a way that looks human. By this I am referring to the dragging of the mouse when a human moves the cursor to a point they are trying to click on. Currently my C# bot moves the mouse instantly to the location which doesn't look human.
private static Point[] FindColor(Color color)
{
int searchValue = color.ToArgb();
List<Point> result = new List<Point>();
using (Bitmap bmp = GetScreenShot())
{
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
if (searchValue.Equals(bmp.GetPixel(x, y).ToArgb()))
result.Add(new Point(x, y));
}
}
}
return result.ToArray();
}
// FUNCTIONS OCCUR BELOW
// Error message if program could not find bitmap within screenshot show error message
Color myRgbColor = new Color(); // Creates new colour called myRgbColor
myRgbColor = Color.FromArgb(51, 90, 9); // This colour equals the RGB value
Point[] points = FindColor(myRgbColor); // Create an array called points which list all the points found in the screen where the RgB value matches.
if (points.Length > 0)
{
Cursor.Position = points[2]; // Move mouse cursor to first point (Point 0)
Thread.Sleep(0200);
MouseClick();
}
if (points.Length == 0)
{
MessageBox.Show("No matches!"); // Return error
goto checkore;
}
You're going to want to use some kind of Timer with a callback, to move the mouse incrementally, step by step. As for the movement itself, you have a world of possibilities, but it's all maths.
So, let's decompose the problem.
What is a natural mouse movement?
Position change rate
It doesn't necessarilly looks like it, but when you move your mouse, you're simply setting its position multiple times per seconds.
The amount of times the position changes per second is equivalent to the polling rate of your mouse. The default polling rate for USB mice is 125Hz (or 125 position changes per second, if you will). This is the value we'll use for our Timer: its callback will be called 125 times per second.
var timer = new Timer(1000 / 125d);
timer.Elapsed += MoveMouse;
void MoveMouse(object sender, ElpasedEventArgs e) { }
Speed and acceleration
When you move your mouse, the distance between two cursor positions is not constant, because you're fast when you start moving your mouse, but you slow down when you get close to the item you want your cursor to be on.
There are also two ways I personally usually move my mouse depending on the context/mood:
One fast uniform movement to get close to the destination, then one slow to correct and get on it (I'll usually go past the destination during the first move)
One medium-slow movement with a small deceleration, follow by a stronger deceleration at the end
The overall speed of the movement also depends on three factors:
The distance between your cursor and the destination
The size of the destination area
Your personal speed
I have absolutely NO IDEA how to work out the formula based on these factors, that's gonna be a work of trial and error for yourself.
This one is purely math and observation based, and will be tricky to get perfectly right, if ever; every person moves their mouse a different way.
The solution I can offer you is to simply forget about deceleration, correction and so on, and just divide your movement into equal steps. That has the merit of being simple.
using System;
using System.Timers;
using System.Drawing;
public class Program
{
static int stepCount = 0;
static int numberOfSteps = 0;
static float stepDistanceX = 0;
static float stepDistanceY = 0;
static PointF destinationPoint;
static Timer timer;
public static void Main()
{
int timerStepDurationMs = 1000 / 125;
PointF currentPoint = Cursor.Position;
destinationPoint = new PointF(2000, 1800); // or however you select your point
int movementDurationMs = new Random().Next(900, 1100); // roughly 1 second
int numberOfSteps = movementDurationMs / timerStepDurationMs;
stepDistanceX = (destinationPoint.X - currentPoint.X) / (float)numberOfSteps;
stepDistanceY = (destinationPoint.Y - currentPoint.Y) / (float)numberOfSteps;
timer = new Timer(timerStepDurationMs);
timer.Elapsed += MoveMouse;
timer.Start();
while (stepCount != numberOfSteps) { }
}
static void MoveMouse(object sender, ElapsedEventArgs e)
{
stepCount++;
if (stepCount == numberOfSteps)
{
Cursor.Position = destinationPoint;
timer.Stop();
}
Cursor.Position.X += stepDistanceX;
Cursor.Position.Y += stepDistanceY;
}
}
Note that I haven't tested with "Cursor", but with some PointF variable instead. It seems to work fine here: dotnetfiddle.

beginner trying to implement a timer in a for loop c#

I'm very new to c# and coding in general and am having some problems implementing a timer in a for loop. Basically, the bit of code below is trying to create a number representative of trash output by an island at set intervals, with each output weighted based on island population to be a bit less predictable. it then adds the generated trash figure to a total. The problem I'm having is that the way tutorials use the Timer class means creating an 'Intervaltimer_Elapsed(object sender, ElapsedEventArgs e)' function outside of Main() and I can't work out how to then add whatever is generated by this back to the weights[] array in the Main(). All I really want to do is as soon as the compiler goes into the for loop, tell it to wait 'x' ticks, then continue. Thread.Sleep isn't an option because this is to go in unity, so would interrupt other things. apologies if the code below is a bit gory!
{
class Program
{
public static double trashperstan8 = 600 * 3.21;
public static int population = 1000;
public static double trashperpersperday = 1;
public static double interval = 60;
public static double intperday = 1440 / interval;
public static double trashperint = population * trashperpersperday * (interval / 1440);
public static int weightnum = population / 200;
static void Main(string[] args)
{
double Trashlevel = new double();
double stand8sfilled = new double();
Timer intervaltimer = new Timer((interval / 30) * 1000);
Console.WriteLine(weightnum);
for (int inti = 0; inti < intperday; inti++)
{
/* at this point, I want to basically tell the code: each time you go
through the for loop, wait for x number of ticks then do the method */
Console.WriteLine(inti);
double[] weights = new double[weightnum];
Random rand = new Random();
for (int i = 0; i < weightnum; i++)
{
double weightcontrib = rand.NextDouble();
weights[i] = weightcontrib;
Console.WriteLine("{0}: {1}", Array.IndexOf(weights, weightcontrib), weightcontrib);
}
double finalweight = 2 * (weights.Sum() / weightnum);
Console.WriteLine("final weight " + finalweight);
double weightedtpi = trashperint * finalweight;
Trashlevel = Trashlevel + weightedtpi;
stand8sfilled = stand8sfilled + (weightedtpi / trashperstan8);
}
Console.WriteLine("trash level " + Trashlevel);
Console.WriteLine("stand8s filled " + stand8sfilled);
}
private static void Intervaltimer_Elapsed(object sender, ElapsedEventArgs e)
{
}
}
}
All I really want to do is as soon as the compiler goes into the for loop, tell it to wait 'x' ticks, then continue. Thread.Sleep isn't an option because this is to go in unity, so would interrupt other things.
Solution 1: Don't write a loop at all. The timer already is logically a loop.
Write a method that is the "body" of the "loop".
"Starting the loop" is activating a timer where the body method is the event handler and the timer fires every n milliseconds
"Terminating the loop" is deactivating the timer.
Solution 2: Write a loop, don't use a timer.
Make the method async and then await Task.Delay(whatever); to asynchronously wait for your delay. Your method will suspend when it hits the await, and resume at some point after the delay task is complete.
The latter is probably the better solution in that the code more closely resembles your description of it.
I don't know enough about Unity to say which is the better solution in their framework.

Dynamic drawing ants in winforms during execution of ant colony

After this question (Show trail of moving pixel in C# WinForm project) for my personal ant colony project in c#, I'm trying to apply the solution second suggested solution: the one that combines drawing the trail into a bitmap and the new ants onto the surface.
[...]Application.Run(new ShowAnts());[...]
public partial class ShowAnts : Form
{
Bitmap bmp;
int j = 0;
public ShowAnts()
{
InitializeAntProgram();
InitializeComponent();
bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
}
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
while (j < 1000)
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c;
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(Brushes.DarkBlue, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
j++;
}
}
}
}
The code above shows the graphic attempt to draw the ant movement into a winform.
It works perfectly, but it shows only the final result. I would like to show the step by step evolution keeping the graphical trail information without reparsing my map info.
Please consider that a working console project on which I' developing this "graphic interface" already exists so:
some variables are set elsewhere (i.e.: food) in the project;the `a.Move(j);` refers to the ant logic itself (analysis, decision, new cell movement referring to the map array);the `j` counter is used to count steps and to set an arbitrary stop, but has no real use;I'm already storing into map array and some other variables all informations concerning pheromone, movement, positions etc.
Looking at your code and also the comments of the previous question, it seems that you are missing the part that would animate the movement. Instead you are looping inside what seems to be the Paint event.
Here is a quick fix for that. It adds a Timer that triggers the RenderAnts event, which seems to be hooked up to the pictureBox1.Paint handler..:
A few class level variables:
int counter = 0;
int limit = 1000;
Timer antTimer = new Timer();
Start code:
antTimer.Interval = 50; // <-- pick your speed !!
antTimer.Tick += (ss, ee) =>
{ pictureBox1.Invalidate(); counter++; if (counter > limit) antTimer.Stop(); };
antTimer.Start();
The speed is 50ms, which means 20 Ticks per second.
The Tick event is inlined with a tiny Lambda epression and has only one statement plus the loop logic. By Invalidating the pictureBox1 control its Paint event and thereby the RenderAnts event is triggered.
Also note that I called it a 'quick fix'. Usually you would discern between the rendering and the moving code of an animation; but in this case this fine difference doesn't matter much.
Now we change the RenderAnts method, taking out the loop:
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
}
}
You also may want to add a Start/Stop Button. Also a TrackBar to change the speed..
Now you should be able to watch the progress of your ants at 20Hz, leaving grey trails.

Finding shortest distance to object based on mouse click in winforms

I am having problems getting this function to work properly. I have to create a winform app that acts as a taxi mapper. On load the taxis are placed in the same location based on a text file. When a user clicks on the form the nearest taxi is supposed to move to the "user" or location, then stop.
Everything is working fine except that the closest taxi does not always go to the location. A taxi further away will go to the location instead. It seems to work some of the time, but not all the time. I am not sure if my logic is correct in the Form1_MouseDown function
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (pickUp) //Are we picking up a passenger?
{
//Convert mouse pointer location to local window locations
int mLocalX = this.PointToClient(Cursor.Position).X;
int mLocalY = this.PointToClient(Cursor.Position).Y;
//set the minimum value (for range finding)
int min = int.MaxValue;
//Temporary object to get the handle for the taxi object we want to manipulate
taxiCabTmp = new TaxiClass();
//Iterate through each object to determine who is the closest
foreach (TaxiClass taxiCab in taxi)
{
if (Math.Abs(Math.Abs(taxiCab.CabLocationX - mLocalX) + Math.Abs(taxiCab.CabLocationY - mLocalY)) <= min)
{
min = Math.Abs(Math.Abs(taxiCab.CabLocationX - mLocalX) + Math.Abs(taxiCab.CabLocationY - mLocalY));
//We found a minimum, grab a handle to the object's instance
taxiCab.GetReference(ref taxiCabTmp);
}
}
//Call the propogate method so it can spin off a thread to slowly change it's location for the timer to also change
taxiCabTmp.Propogate(mLocalX - 20, mLocalY - 20);
taxiCabTmp.occupied = true; //This taxi object is occupied
pickUp = false; //We are not picking up a passenger at the moment
}
else //We are dropping off a passenger
{
taxiCabTmp.Propogate(this.PointToClient(Cursor.Position).X, this.PointToClient(Cursor.Position).Y);
taxiCabTmp.occupied = false;
pickUp = true; //We can pick up a passenger again!
}
}
You are correct that the calculation you use for determining distance will not always be correct. Objects at an angle will calculate to be further away than they really are.
Have a look at this link for more information: http://www.purplemath.com/modules/distform.htm
Here's an example:
int mLocalX = 1;
int mLocalY = 1;
int taxiCab.CabLocationX = 2;
int taxiCab.CabLocationY = 2;
double distance = Math.Sqrt(Math.Pow((taxiCab.CabLocationX - mLocalX), 2) + Math.Pow((taxiCab.CabLocationY - mLocalY), 2));
Just as a side note, you shouldn't append your classes with Class, i.e TaxiClass, it should simply be called Taxi.
Use this formula to calculate distance between two coordinates.
var distance = Math.Sqrt(Math.Pow(taxiCab.CabLocationX - mLocalX, 2) + Math.Pow(taxiCab.CabLocationY - mLocalY, 2));
if (distance <= min) {
min = distance;
//We found a minimum, grab a handle to the object's instance
taxiCab.GetReference(ref taxiCabTmp);
}

C#: ZedGraph Show All Points of Zoomed Area

I am plotting to my data to ZedGraph. Using FileStream to read files. Sometimes my data is greater than 200 megabyte. To draw this amount of data i should calculate peak values or must apply a window. However i want to see the all points of zoomed area. Please share any suggestion.
PointPairList list1 = new PointPairList();
int read;
int count = 0;
while (file.Position < file.Length)
{
read = file.Read(mainBuffer, 0, mainBuffer.Length);
for (int i = 0; i < read / window; i++)
{
list1.Add(count++, BitConverter.ToSingle(mainBuffer, i * window));
count++;
}
}
myCurve1 = zgc.MasterPane.PaneList[1].AddCurve(null, list1, Color.Lime, SymbolType.None);
myCurve1.IsX2Axis = true;
zgc.MasterPane.PaneList[1].XAxis.Scale.MaxAuto = true;
zgc.MasterPane.PaneList[1].XAxis.Scale.MinAuto = true;
zgc.AxisChange();
zgc.Invalidate();
window=2048 for file size between 100 megabyte to 300 megabyte.
Instead of using a PointPairList, I would suggest to use a FilteredPointList instead. By this way, you can keep every points in memory, ZedGraph will only show the points that are necessary for display.
The FilteredPointList class is well explained here.
You will have to change your code a bit this way:
// Load the X, Y points in two double arrays
// ...
var list1 = new FilteredPointList(xArray, yArray);
// ...
// Use the ZoomEvent to adjust the bounds of the filtered point list
void zedGraphControl1_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
{
// The maximum number of point to displayed is based on the width of the graphpane, and the visible range of the X axis
list1.SetBounds(sender.GraphPane.XAxis.Scale.Min, sender.GraphPane.XAxis.Scale.Max, (int)zgc.GraphPane.Rect.Width);
// This refreshes the graph when the button is released after a panning operation
if (newState.Type == ZoomState.StateType.Pan)
sender.Invalidate();
}
Edit
If you can't not host all the points in memory, then you will have to provide your own IPointList implementation for ZedGraph using the logic in the code you describe above. You can inspire from the FilteredPointList itself.
I would use the SetBounds method to preload the points from the disk, based on the decimation algorithm you already implemented, using the min, max and MaxPts in parameters.

Categories

Resources