***I sincerely apologise as I should have posted the complete code.
I have an application where I have an IUIAutomationElementArray and I have cached data regarding bounding rectangles of each IUIAutomationElement from the array. I am then converting these to WPF borders
public class NumberRectangle : Border, IComparable
{
currently I am using iteration to convert the IUIAutomationElementArray to an array list of rectangles seen in the method declaration below.
public ArrayList createRectangles(IUIAutomationElementArray elements)
{
// create an array list to hold the rectangles
rectArray = new ArrayList();
for (int i = 0; i < elements.Length; i++)
{
IUIAutomationElement currentElement = elements.GetElement(i);
//create DragonNumberRectangle to represent automation element
NumberRectangle currentRectangle = new NumberRectangle(currentElement);
//set horizontal and vertical alignment in order to align rectangles properly on window
currentRectangle.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
currentRectangle.VerticalAlignment = System.Windows.VerticalAlignment.Top;
currentRectangle.Height = (currentElement.CachedBoundingRectangle.bottom - currentElement.CachedBoundingRectangle.top);
currentRectangle.Width = (currentElement.CachedBoundingRectangle.right - currentElement.CachedBoundingRectangle.left);
// Thickness object represents Margin property of NumberRectangle (which is basically a Border)
Thickness rectThickness = new Thickness();
//set Left and Top for position of rectangle
rectThickness.Left = (currentElement.CachedBoundingRectangle.left);
rectThickness.Top = (currentElement.CachedBoundingRectangle.top);
currentRectangle.Margin = rectThickness;
// add colour rectangle to the list of rectangles
rectArray.Add(currentRectangle);
}
//sort the rectangles to number from left to right/top to bottom
rectArray.Sort();
return rectArray;
}
I then draw the borders on a WPF window. The issue is that the createRectangles metho takes one second of processing time where the conversion of the element array to rectangles is the predominant time waster.
So the question is can I do this with Linq and how would I do this with Linq, an example would be great as I am not familiar with Linq currently. Perhaps the real question is how do I speed this up?
If you consider LINQ is more elegant than you can use conversion in this way. Surely this is a slower way to convert list of objects.
...
rectArrayList =
from e in elements
select new
{
x = e.x,
y = e.y,
width = e.width,
height = e.height,
};
To achieve a conversion from array to arraylist you could simple do the following:
IUIAutomationElementArray elements = new IUIAutomationElementArray();
//populate that array with data
var arrayList = new ArrayList();
arrayList.Addrange(elements);
Ideally though you should be using a List<T> as opposed to an ArrayList, in which case you could do the following:
List<IUIAutomationElement> myList = new List<IUIAutomationElement>(elements);
Here you are passing the array as a parameter in the constructor of the List.
Related
I have a constantly feeding point array with a length of 4, and want to filter certain "outliers" in the array.
I'm creating a VR/AR app with Opencvforunity and Unity.
Using a live feed from the webcam, I have an 4-length points array which updates and contains x, y 2d coordinates, representing the four corners of a tracked object. And I'm using them as source values to draw a Rect in unity.
Each slot in array contains data such as this:
{296.64151, 88.096649}
However, Unity throws errors and crashes when the a value in the array has
negative values (sometimes happens because of tracking error)
large values exceeding the canvas size (same reason, currently using 1280 x 720)
An example of a "bad value" will be like this :
{-1745.10614, 46.908913} <- negative / big value on X
{681.00519, 1234.15828} <- big value on Y
So I have to somehow create a filter for the array to make the app to work.
The order should not be altered and the data constantly updates so ignoring/skipping bad values will be optimal. I'm new to C# and I have searched but no good luck for "point array"
Here's my code:
Point[] ptsArray = patternTrackingInfo.points2d.toArray();
pt1 = ptsArray[0];
pt2 = ptsArray[2];
pt3 = new OpenCVForUnity.CoreModule.Point(ptsArray[2].x + 5, ptsArray[2].y + 5);
for (int i = 0; i < 4; i++)
{
cropRect = new OpenCVForUnity.CoreModule.Rect(pt1, pt3);
}
pt1 represents the left-top corner and pt2 for right-bottom.
I heard that the right bottom point is exclusive in OpenCV itself so I tried to add a new point to that(pt3), but still crashing - so I believe it is not related to that matter.
Any suggestions for creating a filter for a point array will be very much helpful. Thank you.
I would just create a new list of Points and loop through the existing list, adding only the valid points to the new list. Then that becomes the list that you convert to an array for your OpenCV calls.
List<Point> filteredList = new List<Point>();
for(int i = 0; i < patternTrackingInfo.points2d.Count; i++)
{
if(/*Do your check here*/)
continue;
filteredList.Add(patternTrackingInfo.points2d[i]);
}
Point[] ptsArray = filteredList.toArray();
pt1 = ptsArray[0];
pt2 = ptsArray[2];
pt3 = new OpenCVForUnity.CoreModule.Point(ptsArray[2].x + 5, ptsArray[2].y + 5);
for (int i = 0; i < 4; i++)
{
cropRect = new OpenCVForUnity.CoreModule.Rect(pt1, pt3);
}
I want to create a 2D map of tiles. Example:
Cell[,] cells;
for(int x = 0; x < columns; x++)
{
for(int y = 0; y < rows; y++)
{
cells[x, y] = new Cell();
}
}
The first cell would be at (0|0). What if I want to have this cell as my center and create new cells on the left and top side? These cells would have negative indices.
One way to fix this would be a value that determines the maximum length of one direction. Having a map of 100 tiles per side would place the center of the map at (50|50).
Let's say there would be no hardware limitations and no maximum length per side, what is the best way to create a 2D map with a (0|0) center? I can't image a better way than accessing a cell by its x and y coordinate in a 2D array.
Well, Arrays are logical constructs, not physical ones.
This means that the way we look at the the 0,0 as the top left corner, while might help visualize the content of a 2-D array (and in fact, a 2-D array is also somewhat of a visualization aid), is not accurate at all - the 0,0 "cell" is not a corner, and indexes are not coordinates, though it really helps to understand them when you think about them like they are.
That being said, there is nothing stopping you from creating your own class, that implement an indexer that can take both positive and negative values - in fact, according to Indexers (C# Programming Guide) -
Indexers do not have to be indexed by an integer value; it is up to you how to define the specific look-up mechanism.
Since you are not even obligated to use integers, you most certainly can use both positive and negative values as your indexer.
I was testing an idea to use a list of lists for storage and dynamically calculate the storage index based on the class indexer, but it's getting too late here and I guess I'm too tired to do it right. It's kinda like the solution on the other answer but I was attempting to do it without making you set the final size in the constructor.
Well, you can't use negative indices in an array or list, they're just not the right structure for a problem like this... You could, however, write your own class that handles something like this.
Simply pass in the size of the grid into the constructor, and then use the index operator to return a value based off of an an adjusted index... Something like this... Wrote it up really fast, so it probably isn't ideal in terms of optimization.
public class Grid<T> {
T[,] grid { get; }
int adjustment { get; }
int FindIndex(int provided) {
return provided + adjustment;
}
public Grid(int dimension) {
if (dimension <= 0)
throw new ArgumentException("Grid dimension cannot be <= 0");
if (dimension % 2 != 0)
throw new ArgumentException("Grid must be evenly divisible");
adjustment = dimension / 2;
grid = new T[dimension, dimension];
}
public T this[int key, int key2] {
get {
return grid[FindIndex(key), FindIndex(key2)];
}
set {
grid[FindIndex(key), FindIndex(key2)] = value;
}
}
}
I used these to test it:
var grid = new Grid<int>(100);
grid[-50, -50] = 5;
grid[0, 1] = 10;
You can just switch it to:
var grid = new Grid<Cell>(100);
This only works for a grid with equal dimensions... If you need separate dimensions, you'll need to adjust the constructor and the FindIndex method.
I think that an infinitely sized grid would be dangerous. If you increase the size to the right, you'd have to reposition the center.. Which means, what you think will be at 0,0 will now be shifted as the grid is no longer properly centered.
Additionally, performance of such a structure would be a nightmare as you cannot rely on an array to be infinite (as it inherently isn't). So you'd either have to continuously copy the array (like how a list works) or use a linked list.. If using a linked list, you would have to do enormous amounts of iteration to get whatever value you want.
I am trying to plot a file's byte count over a C# WinForms bar graph. As such, the X-axis will have values 0-255 (if greater than zero) and the Y-axis varies upon the length of the file and the byte distribution. The code is as follows:
for (int i = 0; i < byteDistribution.Count; i++)
{
if (byteDistribution[i] > 0)
{
Series series = new Series(i.ToString());
series.Points.AddXY(i, byteDistribution[i]);
// PointWidth has no affect?
series.SetCustomProperty("PointWidth", "1");
this.crtBytes.Series.Add(series);
}
Questions:
This works well but the way the chart is shown is not to my liking.
I would like each bar to fill in as much space as possible (ie. no
margin / border). From what I've read elsewhere it was suggested to
use PointWidth or PixelPointWidth but none of these approaches is
working.
Is there a way to remove the inner black grid lines from
showing? Ideally, I would like the bottom X-axis numbering to remain just the same, but remove the grid lines.
For removing the gaps:
series["PointWidth"] = "1";
For removing the gridlines:
chartArea.AxisX.MajorGrid = new FChart.Grid {Enabled = false};
chartArea.AxisY.MajorGrid = new FChart.Grid { Enabled = false };
UPDATE:
I think your problem is that you create a new series for each data point. So you also get the "color effect". Just create ONE series, add it to the chart area and add all data points to this series.
Series series = new Series();
this.crtBytes.Series.Add(series);
series.SetCustomProperty("PointWidth", "1");
for (int i = 0; i < byteDistribution.Count; i++)
{
if (byteDistribution[i] > 0)
{
series.Points.AddXY(i, byteDistribution[i]);
// PointWidth has no affect?
}
}
PointWidth property is a relative amount, try something like series["PointWidth"] = 1.25.
The black lines are called MajorGrid, use chartArea.MajorGrid.Enabled = False.
I am making some lists that holds the colour value (0 for black and 1 for white) for each pixel across my image. My problem is when I finish each list it just gives me a single dimensional array that only has got 0s and 1s but I don’t know to which pixel it belong when I want to drew the output image.
Can anyone tell me if I can store location of the pixels as well as the colour value both at the same time in my list? Or any other alternative?
Answering following questions:
Can anyone tell me if I can store location of the pixels as well as
the colour value both at the same time in my list? Or any other
alternative?
If using the .NET Framework 4 or higher, you could use a Tuple to store the values. Fill tuple following way:
var LocXLocYColor = new Tuple<int, int, bool>(1, 1, true);
You could loop through all your these values, using a foreach:
int locx, locy;
bool color;
foreach(var itm in LocXlocYColor)
{
locx = itm.Item1;
locy = itm.Item2;
color = itm.Item3;
}
More Tuple information: MSDN
Above code can be used, when you want to store the pixel locations seperate as integers.
Making use of a Dictionary is another way to achieve your needs:
Create a new dictionary:
Dictionary<Point, bool> locationColor = new Dictionary<Point, bool>();
Fill dictionary with location and color:
locationColor.Add(new Point(1, 1), true);
...
Loop over items in dictionary:
Point location;
bool color;
foreach(KeyValuePair<Point, bool> itm in locationColor)
{
location = itm.Key;
color = itm.Value;th entry.Value or entry.Key
}
If using Point, don't forget to include: System.Drawing; on top of your class.
More Point information: MSDN
Dictionary<Drawing.Point, int> pixelLocations = new Diciontary<Drawing.Point, int>();
Will do what you want.
Edit: Unless you're not storing your locations as points. If they're not Points, then just substitute Drawing.Point for whatever datatype you're using.
You can use your list to know the location of the pixels (this is assuming you know the width or height).
If the pixels were arranged so that the top row of pixels was stored, then the second, etc, you could get the locations like this (where the origin is 1,1):
mylist[wantedY * width - (width - wantedX - 1)]
Where wantedY is the Y-location and wantedX is the X-location.
If, however, the pixels are arranged by column (so that the pixels with x = 0 were taken, then x = 1, etc), you can just use:
mylist[wantedX * height - (height- wantedY - 1)]
Instead of using a list, use a 2-dimensional array
bool[,] isWhite = new bool[bmp.Width, bmp.Height];
and store the values at their corresponding place in this array
isWhite[x, y] = theColor == Color.White;
The location of the pixel is the location within the array. There is no need to store it separately.
I am implementing ZoomableCanvas http://blogs.msdn.com/b/kaelr/archive/2010/08/11/zoomableapplication2-a-million-items.aspx
It's a WPF control that allows for virtualized display of objects in a canvas. To take advantage of the virtualization, the library requires you to implement a method called 'Query' on your datasource object. The Query method lazily returns IEnumerable<int> given a Rect, where the int represents the position in the datasource of the element and the Rect is the visible area of the canvas (items not visible in the canvas are not returned and therefore not drawn). My data source is sorted such that the X and Y values are sorted (myList[0] would contain the smallest X,Y coordinates )
Given this info, I can simply do the following to get my items
int c = this.Count;
for (int j = 0; j < c; j++)
{
if (rectangle.Contains(new Point(this[j].left, this[j].top)))
{
yield return (int)j;
}
}
However, we're traversing the entire list and there's 100k+ items in the list. This performs remarkably badly, especially when viewing the bottom-right of the canvas as those items are at the end of the list.
So I tried transposing the data so that I can take the points in my visible area on the canvas and know exactly what indexes correspond in the array.
var tilewidth = MapWidthInTiles;
for (var x = Math.Max(left, 0); x <= right; x++)
{
for (var y = Math.Max(top, 0); y <= bottom; y++)
{
var i = (y * tilewidth) + x;
if (i < Count)
{
yield return (int)i;
}
}
}
This works except my dataset is irregular (I'm drawing a map), as the map may have missing or incomplete 'tiles'. Hence my array essentially is jagged.
Basically, I'm looking for a way where I can quickly identify elements given a 2D geometry in a 1D array, where the elements in the 2D array may not be complete or contiguous. Normally the [y * widthOfAllItems] + x would give me the proper 2d -> 1d transposition. But because of the missing elements, the equation is off. Any help is appreciated!
You need not to STORE your items in a 1D Array, you need to RETURN them to the ZoomableCanvas in a 1D Array. So feel free to store them in the most efficient way you can think of.
QuadTree might be one solution to store your points : a tree where each node has 4 children NE, SE, SW, NW, (NE=North-East, ...) each one is either empty, filled with one color, or has 4 children also.
Another solution : Working with the islands as base objects, using the bounding box to go faster.... and maybe store the islands in a tree.