I need to find every single cordination in an X and Y KeyPairValue in C#, is there an easy way to do this?
I have the max X and max Y, and the min just starts at 1
int maxX = room.Model.MapSizeX;
int maxY = room.Model.MapSizeY;
Now, I just need to loop every possibility, but I don't really know how to do that, can someone help me with this? I think I just need to loop through everything in X and everything in Y but for every possibility between 1 and max for x and Y
This is simple with nested for loops. Iterate over the first range, and within that, iterate over the second range.
var minX = 1;
var minY = 1;
var maxX = 99;
var maxY = 99;
for (var currentX = minX; currentX <= maxX; ++currentX)
{
for (var currentY = minY; currentY <= maxY; ++currentY)
{
// do something with each X,Y combination
}
}
Related
I'm trying to write a method that given two Point(X,Y) of range 0 to 1000: _startCoord and _endCoord. Cycle through a 2D array lightMap from the _startCoord to the _endCoord, modifying each element in the area between the two points.
I've made this illustration as an example, I'm trying to modify all the elements within quad A, given: _startCoord as some corner Point and _endCoord as the opposite corner Point
I've been trying to figure out a method that works in any "direction", for example:
From 500,500 to 250,750 WHERE x decrements, y increments
or 500,500 to 750,150WHERE x increments, y decrements etc
Here's my latest attempt:
struct Point {
public int xPos;
public int yPos;
public Point(int _x, int _y) {
xPos = _x;
yPos = _y;
}
}
//Given two corner points, toggle the elements between the points
static void ToggleBits(Point _startCoord, Point _endCoord) {
//Determine direction to iterate on each axis
int xDir = (_startCoord.xPos > _endCoord.xPos) ? -1 : 1;
int yDir = (_startCoord.yPos > _endCoord.yPos) ? -1 : 1;
int currentX = _startCoord.xPos;
int currentY = _startCoord.yPos;
//Account for single point (points are the same)
if (_startCoord.xPos == _endCoord.xPos && _startCoord.yPos == _endCoord.yPos) {
lightMap[currentX, currentY] = !lightMap[currentX, currentY]; //Toggle element at current indices
return;
}
//While both indices not met
while (currentX != _endCoord.xPos || currentY != _endCoord.yPos) {
Console.WriteLine(currentX + ","+currentY);
lightMap[currentX, currentY] = !lightMap[currentX, currentY]; //Toggle element at current indices
if (currentX == _endCoord.xPos) { //Reached endX
if (currentY != _endCoord.yPos) { //But not reached endY
currentY += yDir; //Increment y axis
currentX = _startCoord.xPos; //Return to column start
}
}
else if (currentY == _endCoord.yPos) { //Reached endY
if (currentX != _endCoord.xPos) { //But not reached endX
currentX += xDir; //Increment x axis
currentY = _startCoord.yPos; //Return to row start
}
} else { //Neither indices reached increment x axis
currentX += xDir; //Increment x axis
}
}
}
Input
ToggleBits(new Point(5,0), new Point(6,10));
Output
5,0
6,0
5,1
6,1
5,2
6,2
5,3
6,3
5,4
6,4
5,5
6,5
5,6
6,6
5,7
6,7
5,8
6,8
5,9
6,9
5,10
6,0
5,1
6,1
5,2
6,2
...Infinite Loop...
It is so close to working correctly, but as I reset the row/column and increment the column/row, I reset the progress and do it again...forever. Any help is appreciated, thanks in advance!
I'm not sure if I fully understand, what you are trying to do, but can't you just go in two nested for-loops from the min to the max?
var minX = Math.Min(_startCoord.X, _endCoord.X);
var maxX = Math.Max(_startCoord.X, _endCoord.X);
var minY = Math.Min(_startCoord.Y, _endCoord.Y);
var maxY = Math.Max(_startCoord.Y, _endCoord.Y);
for (var x = minX; x < maxX; x++)
{
for (var y = minY; y < maxY; y++)
{
// do something to lightMap[x, y]
}
}
I have a BackgroundWorker and a single ProgressBar. When working, the BackgroundWorker runs through a triple for-loop and reports progress to the ProgressBar.
Currently, the progress that is being reported is only that of the outter-most loop (xProgress), which works, but does not run smoothly. The goal is for the ProgressBar to also account for the progress percentages of the inner loops, so that the ProgressBar updates more smoothly and more accurately.
The DoWork method:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int xMax, yMax, zMax;
xMax = 10;
for (int x = 1; x <= xMax; x++)
{
yMax = 5;
for (int y = 1; y <= yMax; y++)
{
zMax = new Random().Next(50, 100);
for (int z = 1; z <= zMax; z++)
{
Thread.Sleep(5); /// The process
double xProgress = (double)x / (double)xMax;
double yProgress = (double)y / (double)yMax;
double zProgress = (double)z / (double)zMax;
/// The progress calculation:
double progressCalc = xProgress;
int progress = (int)(progressCalc * pgb.Maximum);
bgw.ReportProgress(progress);
}
}
}
}
This works even if you don't know your best/worst case in advance.
Any of the max's could be randomized in the same fashion of zMax.
static void F()
{
var r = new Random();
int xMax = 10;
int yMax = 5;
int zMax;
for (int x = 0; x < xMax; x++)
{
double xProg = (double)x / xMax;
for (int y = 0; y < yMax; y++)
{
double yProg = (double)y / (yMax * xMax);
zMax = r.Next(50, 100);
for (int z = 0; z < zMax; z++)
{
double zProg = (double)z / (zMax * yMax * xMax);
var prog = xProg + yProg + zProg;
Console.WriteLine(prog.ToString("P"));
// bgw.ReportProgress((int)(prog * pgb.Maximum));
}
}
}
Console.WriteLine(1.ToString("P")); // Make sure to report the final 100%
// bgw.ReportProgress((int)pgb.Maximum);
}
Btw, I'd replace the pgb.Maximum's with 1 and in the OnProgressHandler multiply the progress by it. That way the threaded method does not touch UI elements at all.
It's true that you can't know exactly how many iterations your loops will do, but you certainly can smooth your progress indicator.
Let's assume your total iterations in the worst case is xMax * yMax * worstZMax.
worstZMax = 99 because the upper bound is exclusive in Random.Next(minValue:int, maxValue:int)
Hence the total iterations in worst case scenario will be 5 * 10 * 99 = 4950.
Now we could start with that total and adjust it as required when we loose iterations after generating zMax for each y loop and we'll effectively smooth the progress calculation and reporting.
This is how I'd do it:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
const int xMax = 10;
const int yMax = 5;
const int worstZMax = 99; //because upper is exclusive in Random.Next(lower, upper)
var iteration = 0;
var total = xMax * yMax * worstZMax; //total number of iterations (worst case)
for (var x = 1; x <= xMax; x++)
{
for (var y = 1; y <= yMax; y++)
{
var zMax = new Random().Next(50, 100);
//get how many iterations did we miss, and adjust the total iterations
total -= worstZMax - zMax;
for (var z = 1; z <= zMax; z++)
{
iteration++; //count this iteration
Thread.Sleep(5); // The process
// The progress calculation
var progress = (double)iteration / total * pgb.Maximum;
bgw.ReportProgress((int)progress);
}
}
}
}
Hope this helps!
Updated Answer:
Since inner loop has unknown number of iterations you could decide how many steps it should advance. for example 10.
Then you could do something like this:
progressbarMaximum = xMax * yMax * 10
right before z-loop you get the zModulo by dividing zMax with 10.
in your z-loop check if
zMax % zModulo == 0
then increment progressbar.
Old answer:
If you multiply xMax, yMax and zMax you get the total number of iterations of the innermost loop.
Set progressbar maximum to that value.
On each iteration of the inner loop increment progressbar.
You can't make it exact. Think of it this way - what if the first randoms were all 50 and you have already done half of the 2 outer loops - if the rest of the randoms will be 50 - you've done 50%. If the rest of the randoms will be 100 - you will only have done 33%. So you don't know how far the progress bar should be.
(Of course random results won't usually be like that. It's just to illustrate the point.)
I need to extract a black/white image (signature) from within a white bitmap canvas and resize it to specific dimensions. The image (sig) is guaranteed to be black on a white background.
The reason is that when we capture the signature, some people write tiny, other fill the capture area. However, I need them all to end up to fill the edges of another image for further processing.
I need to find the X/Y coordinates / rectangle boundary of the signature so I can extract just that portion of the canvas, and not end up with lots of surrounding white space.
I noticed this in a different project, and want to know how to implement in OpenCVSharp.
http://www.emgu.com/wiki/index.php/Minimum_Area_Rectangle_in_CSharp
thanks.
EDIT: As pointed out by Miki in the comments, you may be searching for the rotated box. You probably want OpenCvSharp.Cv.MinAreaRect2(), which takes a CvArr of points, and returns a CvBox2D.
Reference
Bounding box calculations are relatively simple as long as you aren't worried about tilt in the bounding box, finding the minimum enclosing rectangle is just a matter of finding the smallest and largest x and y that correspond to a black pixel. The simplest method would be something like:
// You would actually use your image
Bitmap b = new Bitmap(640,480);
// For the demonstration generate some randomized data
Random r = new Random();
for (int i = 0; i < 1000; i++)
{
b.SetPixel(r.Next(200) + 50, r.Next(200) + 50, Color.Black);
}
int minX, minY;
int maxX, maxY;
minX = minY = int.MaxValue;
maxX = maxY = int.MinValue;
// Find the minimum and maximum black coordinates
for (int x = 0; x < b.Width; x++)
{
for (int y = 0; y < b.Height; y++)
{
if (b.GetPixel(x,y).ToArgb() == Color.Black.ToArgb())
{
if (x > maxX) maxX = x;
if (x < minX) minX = x;
if (y > maxY) maxY = y;
if (y < minY) minY = y;
}
}
}
// Draw a bounding box for the demonstration
using (Graphics g = Graphics.FromImage(b))
{
Pen red = new Pen(Color.Red);
g.DrawRectangle(red, minX, minY, maxX - minX, maxY - minY);
}
b.Save("c:\\tmp\\test.png");
This is admittedly not the cleanest implementation, but any algorithm for searching for a minimum and maximum will work. (You just have to do it for both dimensions.)
I am new to c# programming and creating my first Windows forms application. I have a two 1-D Arrays, one represents the X Axis Values and the other represents Y axis.
I am trying to create a graph from them using the following code.
public void drawgraph()
{
chart1.Series["Series1"].Name = MemsName;
for (int i = 0; i < VmicArray.Length; i++)
{
chart1.Series[MemsName].Points.AddXY(VmicArray[i], SensitivityArray[i]);
}
chart1.ChartAreas[0].AxisX.Title = "Vmic Value";
chart1.ChartAreas[0].AxisY.Title = "Sensitivity";
}
I am getting the XAxis values which I have in Array(like -2.333333754 or 6.46870) with the interval of 5 which I have set. The range of X axis is have is from -4 to +8.
Is there anyone who can help me in getting a ouput like we get in Excel Graphs? I am trying for Long time always I mess up with the values of X axis.
I Need the graph with XAxis value from -10 to +10 with the interval of 1 and mapping the Y values to corresponding X values on graph.
Unfortunately I am not able to post any Images :(
If you want to project a certain range of values to another range you need to use linear interpolation between the values. First determine the old min and max values (MinX and MaxX) and define the new limits (-10, 10).
Then use a simple formula to determine the new x value of an arbitrary old value.
double MinX = VmicArray.min;
double MaxX = VmicArray.Max;
double NewMin = -10;
double NewMax = 10;
for (i = 0; i <= VmicArray.Count - 1; i++) {
// Linear interpolation
double NewX = VmicArray(i) / (MaxX - MinX) * (NewMax - NewMin) + NewMin;
}
Recalculate each X value before you use AddXY.
In order to just change the visible bounds of each axis you can use the XAxis.Minimum and XAxis.Maximum as well as the XAxis.Interval properties:
chart1.ChartAreas[0].AxisX.Minimum = -10;
chart1.ChartAreas[0].AxisX.Maximum = 10;
chart1.ChartAreas[0].AxisX.Interval = 1;
I have the following code:
int width = 10;
int height = 7;
bool[,] array1 = new bool[width, height];
string values =
"1100000000" +
"1100000011" +
"0001100011" +
"0001100000" +
"0001110000" +
"0000000110" +
"0000000110";
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
array1[x, y] = (values[x + y * width] == '1');
}
}
im looking for a algorithm that would extract Ranges where we have a 1.
so from this data we would get rectangles
(0,0,2,2),
(8,1,2,2),
(3,2,3,3),
(7,5,2,2)
the order of the rectangles do not matter!
But i have no idea how to do this any one got any pointers?
After reading Rusty Weber answer i came up with the following:
private static List<Rectangle> GetRectangles(bool[,] array)
{
List<Rectangle> rectangles = new List<Rectangle>();
for (int x = 0; x < array.GetLength(0); x++)
{
for (int y = 0; y < array.GetLength(1); y++)
{
if (array[x, y])
{
rectangles.Add(GetRectangle(array, new Point(x, y)));
}
}
}
return rectangles;
}
static Rectangle GetRectangle(bool[,] array, Point startLocation)
{
int maxX = int.MinValue;
int minX = int.MaxValue;
int maxY = int.MinValue;
int minY = int.MaxValue;
HashSet<Point> visitedLocations = new HashSet<Point>();
Stack<Point> pointsToGo = new Stack<Point>();
Point location;
pointsToGo.Push(startLocation);
while (pointsToGo.Count > 0)
{
location = pointsToGo.Pop();
if (!location.X.IsBetween(0, array.GetLength(0) - 1))
continue;
if (!location.Y.IsBetween(0, array.GetLength(1) - 1))
continue;
if (!array[location.X, location.Y])
continue;
if (visitedLocations.Contains(location))
continue;
visitedLocations.Add(location);
pointsToGo.Push(new Point(location.X + 1, location.Y));
pointsToGo.Push(new Point(location.X, location.Y + 1));
pointsToGo.Push(new Point(location.X - 1, location.Y));
pointsToGo.Push(new Point(location.X, location.Y - 1));
}
foreach (Point location2 in visitedLocations)
{
array[location2.X, location2.Y] = false;
if (location2.X > maxX)
maxX = location2.X;
if (location2.X < minX)
minX = location2.X;
if (location2.Y > maxY)
maxY = location2.Y;
if (location2.Y < minY)
minY = location2.Y;
}
return new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
}
public static bool IsBetween<T>(this T item, T start, T end)
{
return Comparer<T>.Default.Compare(item, start) >= 0
&& Comparer<T>.Default.Compare(item, end) <= 0;
}
COMMENT :: It might help me to answer your question if you have better defined coordinates. (0,0,2,2) isn't exactly Cartesian and it may need some explaining. Is this the top left corner followed by the widths?
Ok. The easiest to program way, in my opinion at least, to extract all possible rectangles from the graph is to have a recursively defined method that searches in a specific direction for the symmetric rectangle pattern. This however could end up being really slow so I hope that speed isn't a constraint for you. Looking at the style of code, I would say that this is a school assignment for either recursion or dynamic programming.
something along the lines of the following pseudocode
`
for i in width
{
for j in height
{
if(point[i,j] == 1)
{
potentials = searh_in_direction(i,j,graph,width,height,RIGHT,[[i,j]] )
listOfAllRects.append(potentials)
}
}
}
list_of_rectangle searh_in_direction(i,j,graph,width,height,direction, listofpoints )
{
nextdirection = direction.nextdirection; //Right -> down -> left-> up
//DEVELOP METHOD FOR RECURSION HERE THAT RETURNS ALL SETS OF 4 POINTS THAT
for every point in the direction of travel
if the point is the origional point and we have 4 points including the point we are looking at, we have a rectangle and we need to return
if point on direction of travel is a one travel on the next direction
posiblerects.append(searh_in_direction(i,j,graph,width,height,nextdirection , listofpoints.append(currentpoint)))
//after all points in direction have bee searched
return posiblerects.
}
`
I know that this code could be very confusing but that is the gist of what you need as a recursive element.
I will also note that I can already see several bugs in this code but I have run out of the 15 minutes that I said that I was going to spend on this post so you might have to pick them out yourself.
This gives you the same results you're looking for:
static void Main(string[] args)
{
string values =
"1100000000" +
"1100000011" +
"0001100011" +
"0001100000" +
"0001110000" +
"0000000110" +
"0000000110";
int width = 10;
int height = 7;
bool[,] array = new bool[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
array[x, y] = (values[x + y * width] == '1');
List<Rectangle> rectangles = new List<Rectangle>();
for (int x = 0; x < width; ++x)
{
for (int y = 0; y < height; ++y)
{
if (array[x, y] && !Used(rectangles, x, y))
{
int rHeight = 1;
for (int rX = x + 1; rX < width && array[rX, y] && !Used(rectangles, rX, y); ++rX)
for (int rY = y + 1; rY < height && array[rX, rY] && !Used(rectangles, rX, rY); ++rY)
if (rY - y >= rHeight)
rHeight = rY - y + 1;
int rWidth = 1;
for (int rY = y + 1; rY < height && rY - y <= rHeight && array[x, rY] && !Used(rectangles, x, rY); ++rY)
for (int rX = x + 1; rX < width && array[rX, rY] && !Used(rectangles, rX, rY); ++rX)
if (rX - x >= rWidth)
rWidth = rX - x + 1;
rectangles.Add(new Rectangle(x, y, rWidth, rHeight));
}
}
}
foreach (Rectangle rect in rectangles)
Console.WriteLine(rect);
}
private static bool Used(IEnumerable<Rectangle> rectangles, int x, int y)
{
return rectangles.Any(r => r.Contains(x, y));
}
I made an adhoc Rectangle struct since I didn't reference System.Drawing, but you can pass a System.Drawing.Point to the System.Drawing.Rectangle.Contains() and get the same results.
Also, notice that the width of your array should actually be 10 and your indexing math was wrong. You should be multiplying y by the width, not the height.
It is not clear from the question if you really want rectangles that cover the 1's exactly, or if you want bounding volumes that can contain zeroes, but will cover all the 1's with a reasonably small number of rectangles.
Assuming you want rectangles to cover the 1's, and you don't need a perfect solution:
Make a temporary copy of the array.
Iterate over the temporary looking for 1's
When you hit a 1, begin a new rectagle that starts as 1x1, offset to that location ( e.g. covers just that 1 )
Expand that rectangle rightward so long as there is a 1 in the next cell
Expand that rectangle downards so long as the row below has 1's matching the width
of the current rectangle.
ONce you can't expand down any more, emit that recgantle, and clear all the 1's covered by that rectangle from the temporary
continue scanning for 1's starting with the cell directly after the top right corner of the current rectangle.
This will produce a decent covering - but by no means ideal. If you need a perfect covering - e.g. the guaranteed minimum number of rectangles then it is harder.