Xamarin find child fast with point - c#

I would like the search for a child on a grid to be super fast. The code I've created now is probably not the fastest way. I've tried implementing the 'GetChildElements()' but it doesn't return any of the children where my code does. Any suggestions on how to make this lighting fast?
touches contains any relatve touched Point(s) within the grid.
private void GetChildWithFrequency(object sender, Point[] touches)
{
Layout<View> grid = (Layout<View>)sender;
foreach (Key child in grid.Children)
{
if (touches[0].X >= child.X &&
touches[0].X <= child.X + child.Width &&
touches[0].Y >= child.Y &&
touches[0].Y <= child.Y + child.Height)
{
child.LastX = touches[0].X;
if (LastChild != null)
{
LastChild.Selected = false;
}
LastChild = child;
child.Selected = true;
break;
}
}
}

if you have a regular grid of cells and each row is R high and each column is C wide, then a touch at X,Y
Row = Y / R;
Col = X / C;
for instance, if R = 50 and C = 50, then a touch at (120,410) would be
Row = 410 / 50 ==> 8
Col = 120 / 50 ==> 2
if you Grid does not start at 0,0 you will need to adjust for that

Related

How To Know When AdaptativeGridView Will Use One, Two, Three (or More) Columns

I`m using an AdaptativeGridView, with DesiredWidth of 488.
I thought that when the grid had ActualWidth of 684, for exemple, it would use two columns, because 684 is 196 pixels distant from the DesiredWidth (488), as 684/2 (if use two columns) result in 342, witch is only 146 pixels distant from DesiredWidth. But, different from the expected, the grid keep only one column, until the ActualWidth reach some value that I don't understand how it is defined.
I tried to calculate the definition of columns number, trying to check if the number of pixels is more close from the target (DesiredWidth) using only one or using two columns, but the logic didn't work. I need to understand how DesiredWidth logic works.
Here is my logic:
var twoColumns = Math.Abs(AppWebsiteGridView.DesiredWidth - (AppWebsiteGridView.ActualWidth / 2));
var oneColumn = Math.Abs(AppWebsiteGridView.ActualWidth - AppWebsiteGridView.DesiredWidth);
var threeColumns = Math.Abs(AppWebsiteGridView.DesiredWidth - (AppWebsiteGridView.ActualWidth / 3));
var numberOfItems = AppWebsiteGridView.Items.Count;
if (AppWebsiteGridView.Items[numberOfItems - 1] is SignInModel lastItem && AppWebsiteGridView.Items[numberOfItems - 2] is SignInModel lastButOneItem
&& AppWebsiteGridView.Items[numberOfItems - 3] is SignInModel lastButTwoItem)
{
if (threeColumns < twoColumns)
{
lastItem.IsEndLine = false;
lastButOneItem.IsEndLine = false;
lastButTwoItem.IsEndLine = false;
}
else if (twoColumns < oneColumn)
{
lastItem.IsEndLine = false;
lastButOneItem.IsEndLine = false;
lastButTwoItem.IsEndLine = true;
}
else
{
lastItem.IsEndLine = false;
lastButOneItem.IsEndLine = true;
lastButTwoItem.IsEndLine = true;
}
}

Find points with maximum visibility in a room-as-grid

I have a 2D grid of cells, like so:
I want to find the "centroids," or the places in each room that can see the most other cells. For example, "centroid" 1 can see 500 other cells, "centroid" 2 can see 400 other cells (NOT included in the first 500), and so on (if there's a better name for this let me know).
I'm currently doing this with the code below.
public void SetCentroids(CellWalkableState[,] grid)
{
centroids = new List<((int, int), int)>();
List<(int, int)> cellsCopy = new List<(int, int)>();
for (int i = 0; i < cells.Count; i++)
{
cellsCopy.Add(cells[i]);
}
Debug.Log(DateTime.Now.ToString("o") + " - Setting centroids for room with " + cells.Count + " cells");
var perCellInView = cellsCopy.AsParallel().Select(x => (x, StaticClass.FindInView(x, grid))).ToList();
var force_start = perCellInView.First();
Debug.Log(DateTime.Now.ToString("o") + " - got in view");
var perCellInViewOrdered = perCellInView.AsParallel().OrderByDescending(xxx => xxx.Item2.Count);
var force_start_1 = perCellInViewOrdered.First();
Debug.Log(DateTime.Now.ToString("o") + " - sorted");
List<(int, int)> roomCellsAdded = new List<(int, int)>();
while(roomCellsAdded.Count < (cells.Count*0.9))
{
if(cellsCopy.Count == 0)
{
Debug.LogError("something is wrong here.");
}
var centroid = perCellInViewOrdered.First().x;
var centroidCells = perCellInViewOrdered.First().Item2;
if(centroidCells.Count == 0)
{
Debug.Log("this shouldnt be happening");
break;
}
roomCellsAdded.AddRange(centroidCells);
centroids.Add((centroid, centroidCells.Count));
Debug.Log(DateTime.Now.ToString("o") + " - added centroids, " + roomCellsAdded.Count + " cells in view");
var loopPerCellInView = perCellInView.AsParallel().Where(x => centroids.Select(y => y.Item1).Contains(x.x) == false).Select(x => (x.x, x.Item2.Except(roomCellsAdded).ToList())).ToList();
Debug.Log(DateTime.Now.ToString("o") + " - excluded");
perCellInViewOrdered = loopPerCellInView.AsParallel().OrderByDescending(xxx => xxx.Item2.Count);
Debug.Log(DateTime.Now.ToString("o") + " - resorted");
}
}
public static List<(int, int)> FindInView((int,int) start, CellWalkableState[,] grid)
{
List<(int, int)> visible = new List<(int, int)>() { start };
bool alive = true;
int r = 1;
var length_x = grid.GetLength(0);
var length_y = grid.GetLength(1);
List<(int, int)> searched = new List<(int, int)>();
List<double> angles = new List<double>();
while(alive)
{
//alive = false;
int newR = r;
int count = CountFromR(newR);
var angleInc = 360.0 / count;
var rNexts = Enumerable.Repeat(1, count).ToArray();
for (int i = 0; i < count; i++)
{
var angle = angleInc * i;
if(angles.Contains(angle) == false)
{
angles.Add(angle);
float cos = Mathf.Cos((float)(Mathf.Deg2Rad * angle));
float sin = Mathf.Sin((float)(Mathf.Deg2Rad * angle));
var b = r;
var p = i % (r * 2);
var d = math.sqrt(math.pow(b, 2) + math.pow(p, 2));
var dScaled = d / r;
bool keepGoing = true;
while(keepGoing)
{
var rCur = dScaled * (rNexts[i]);
var loc = (start.Item1 + Mathf.RoundToInt(rCur * cos), start.Item2 + Mathf.RoundToInt(rCur * sin));
if (searched.Contains(loc) == false)
{
searched.Add(loc);
if (loc.Item1 >= 0 && loc.Item1 < length_x && loc.Item2 >= 0 && loc.Item2 < length_y)
{
if (grid[loc.Item1, loc.Item2] == CellWalkableState.Interactive || grid[loc.Item1, loc.Item2] == CellWalkableState.Walkable)
{
visible.Add(loc);
}
else
{
keepGoing = false;
}
}
else
{
keepGoing = false; // invalid, stop
}
}
else
{
if (visible.Contains(loc) == false)
{
keepGoing = false; // can stop, because we can't see past this place
}
}
if(keepGoing)
{
rNexts[i]++;
}
}
}
}
angles = angles.Distinct().ToList();
searched = searched.Distinct().ToList();
visible = visible.Distinct().ToList();
if(rNexts.All(x => x <= r))
{
alive = false;
}
else
{
r = rNexts.Max();
}
}
return visible;
}
static int CountFromR(int r)
{
return 8 * r;
}
The "short" summary of the code above is that each location first determines what cells around itself it can see. That becomes a list of tuples, List<((int,int), List<(int,int)>)>, where the first item is the location and the second is all cells it views. That main list is sorted by the count of the sublist, such that the item with the most cells-it-can-vew is first. That's added as a centroid, and all cells it can view are added to a second ("already handled") list. A modified "main list" is formed, with each sublist now excluding anything in the second list. It loops doing this until 90% of the cells have been added.
Some output:
2021-04-27T15:24:39.8678545-04:00 - Setting centroids for room with 7129 cells
2021-04-27T15:45:26.4418515-04:00 - got in view
2021-04-27T15:45:26.4578551-04:00 - sorted
2021-04-27T15:45:27.3168517-04:00 - added centroids, 4756 cells in view
2021-04-27T15:45:27.9868523-04:00 - excluded
2021-04-27T15:45:27.9868523-04:00 - resorted
2021-04-27T15:45:28.1058514-04:00 - added centroids, 6838 cells in view
2021-04-27T15:45:28.2513513-04:00 - excluded
2021-04-27T15:45:28.2513513-04:00 - resorted
2021-04-27T15:45:28.2523509-04:00 - Setting centroids for room with 20671 cells
This is just too slow for my purposes. Can anyone suggest alternate methods of doing this? For all of the cells essentially the only information one has is whether they're "open" or one can see through them or not (vs something like a wall).
An approximate solution with fixed integer slopes
For a big speedup (from quadratic in the number of rooms to linear), you could decide to check just a few integer slopes at each point. These are equivalence classes of visibility, i.e., if cell x can see cell y along such a line, and cell y can see cell z along the same line, then all 3 cells can see each other. Then you only need to compute each "visibility interval" along a particular line once, rather than per-cell.
You would probably want to check at least horizontal, vertical and both 45-degree diagonal slopes. For horizontal, start at cell (1, 1), and move right until you hit a wall, let's say at (5, 1). Then the cells (1, 1), (2, 1), (3, 1) and (4, 1) can all see each other along this slope, so although you started at (1, 1), there's no need to repeat the computation for the other 3 cells -- just add a copy of this list (or even a pointer to it, which is faster) to the visibility lists for all 4 cells. Keep heading right, and repeat the process as soon as you hit a non-wall. Then begin again on the next row.
Visibility checking for 45-degree diagonals is slightly harder, but not much, and checking for other slopes in which we advance 1 horizontally and some k vertically (or vice versa) is about the same. (Checking for for general slopes, like for every 2 steps right go up 3, is perhaps a bit trickier.)
Provided you use pointers rather than list copies, for a given slope, this approach spends amortised constant time per cell: Although finding the k horizontally-visible neighbours of some cell takes O(k) time, it means no further horizontal processing needs to be done for any of them. So if you check a constant number of slopes (e.g., the four I suggested), this is O(n) time overall to process n cells. In contrast, I think your current approach takes at least O(nq) time, where q is the average number of cells visible to a cell.

How can I speed up this image matching code in EmguCV C# code?

Here's the code. See the commented line for where possible optimization could be (at the foreach). Anyone have suggestions on improving the speed here?
public void FindMatches(Matrix<float> dbDescriptors, Matrix<float> queryDescriptors, ref IList<IndecesMapping> imap)
{
var indices = new Matrix<int>(queryDescriptors.Rows, 2); // matrix that will contain indices of the 2-nearest neighbors found
var dists = new Matrix<float>(queryDescriptors.Rows, 2); // matrix that will contain distances to the 2-nearest neighbors found
// create FLANN index with 4 kd-trees and perform KNN search over it look for 2 nearest neighbours
var flannIndex = new Index(dbDescriptors, 4);
flannIndex.KnnSearch(queryDescriptors, indices, dists, 2, 24);
for (int i = 0; i < indices.Rows; i++)
{
// filter out all inadequate pairs based on distance between pairs
if (dists.Data[i, 0] < (0.5 * dists.Data[i, 1]))
{
// find image from the db to which current descriptor range belongs and increment similarity value.
// in the actual implementation this should be done differently as it's not very efficient for large image collections.
foreach (var img in imap)
{
if (img.IndexStart <= indices[i, 0] && img.IndexEnd >= indices[i, 0])
{
img.Similarity++;
break;
}
}
}
}
}
You can improve your work by changing foreach loop as following:
foreach (var img in imap)
{
if (img.IndexStart <= indices[i, 1] && img.IndexEnd >= indices[i, 1])
{
img.Similarity++;
break;
}
}
Then it is working fine

Get the Range of Lat Long with in specified Radius in c#

I am working on a website in which I have the User's Location Lat and Long saved in my Location table. Now I want to use a filter SearchByDistance which have values: 5km, 10km, 15km through which the user can get the results according to the specified Range.
Now what I actually wants to do is to get the input from the user say 5km and get the results from my table which falls with in the range of user's saved LatLong in the Location table and 5km to that LatLong. I google on this and found some links like:
How do I find the lat/long that is x km north of a given lat/long
http://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate.getdistanceto%28v=vs.110%29.aspx
But I am unable to get my requirement from the above. Please help. Thanks
I think your approach can be, first create a circle (your center will be user lat and long) with the given radius say 5KM or 10Km and then find the rows from the Polygon Rings. I wrote it for esri maps. Hope it will solve your problem
Polygon areaOfInterset;
void CreateCircle(double radius)
{
var point = new MapPoint(Your Lat and Long);// This will be user lat and long on which you want to draw a circle
var graphic = new Graphic();
var circle = new ESRI.ArcGIS.Client.Geometry.PointCollection();
int i = 0;
while (i <= 360)
{
double degree = (i * (Math.PI / 180));
double x = point.X + Math.Cos(degree) * radius;
double y = point.Y + Math.Sin(degree) * radius;
circle.Add(new MapPoint(x, y));
i++;
}
var rings = new ObservableCollection<ESRI.ArcGIS.Client.Geometry.PointCollection> { circle };
areaOfInterset = new Polygon { Rings = rings};
}
Now next task is to find the rows. For that you can use below code inside the loop.
foreach(MapPoint selectedRow in DatabaseRowsToBeSearched)
{
var isExist = IsInsideCircle(selectedRow)
}
bool IsInsideCircle(MapPoint location)
{
var isInside = false;
foreach (var shape in areaOfInterset.Rings)
{
for (int i = 0, j = shape.Count - 1; i < shape.Count; j = i++)
{
if ((((shape[i].Y <= location.Y) && (location.Y < shape[j].Y)) ||
((shape[j].Y <= location.Y) && (location.Y < shape[i].Y))) &&
(location.X < (shape[j].X - shape[i].X) * (location.Y - shape[i].Y) / (shape[j].Y - shape[i].Y) + shape[i].X))
{
isInside = !isInside;
}
}
}
return isInside;
}

Add a Keyword Cloud in ASP.NET Page

I need to add a keyword cloud in my asp net web pages! Can anyone suggest me the best way to do it? I got a few working samples implemented using C# but I want to know if there are other possibilities to do that! Any good suggestion would be really appreciated! Thanks in advance :)
you can try using this code..
Int32 rank, minVal, maxVal, scale, s;
minVal = st.GetMinRank();
maxVal = st.GetMaxRank();
scale = (maxVal - minVal) / 6;
rank = Convert.ToInt32(yourRankValue that is stored in your DB);
if (scale == 0)
s = 0;
else
s = (rank - minVal) / scale;
if (s == 0)
{
lblSTName.Font.Size = FontUnit.Smaller;
}
else if (s == 1)
{
lblSTName.Font.Size = FontUnit.Small;
}
else if (s == 2)
{
lblSTName.Font.Size = FontUnit.Medium;
}
else if (s == 3)
{
lblSTName.Font.Size = FontUnit.Large;
}
else if (s == 4)
{
lblSTName.Font.Size = FontUnit.Larger;
}
else if (s >= 5)
{
lblSTName.Font.Size = FontUnit.Larger;
lblSTName.Font.Bold = true;
}
I guess to some extent, the answer depends on how and where your keyword data is stored.
I have a database with the following tables:
So Photos are linked to Tags through the TagsPhotos table.
I then used the following methods to generate my keyword cloud:
protected void Page_Load(object sender, EventArgs e) {
// "zhpCtx" is a LINQ to SQL data context.
// "TagCloud" is a Panel control.
// Select a list of tags and a count of how often they appear in TagsPhotos
var tagDensity = from t in zhpCtx.siteContent_Tags
join tp in zhpCtx.siteContent_TagsPhotos
on t.TagID equals tp.TagID
group t by new { t.TagID, t.TagText } into g
where g.Count() > 0
orderby g.Key.TagText
select new { g.Key.TagID, g.Key.TagText, NumTags = g.Count() };
if (null != tagDensity && tagDensity.Count() > 0) {
// We have some tags, get the lowest number of counts greater than 0, and
// the highest to give our range.
int? min = tagDensity.Min(t => t.NumTags);
int? max = tagDensity.Max(t => t.NumTags);
// Loop through each tag
foreach (var tag in tagDensity) {
// Create a new HyperLink control to take the user to a given tag
// Include the tag count in the list for accessibility.
// Could probably move it to the title attribute.
// Build the link however suits.
HyperLink tagLink = new HyperLink {
NavigateUrl = string.Format("Photos.aspx?TagID={0}", tag.TagID),
Text = string.Format("{0} ({1})", tag.TagText, tag.NumTags) };
// Adjust the font-size of the tag link - calling getPercentage.
// This will adjust the size based on the baseline font size for the
// container
tagLink.Style.Add("font-size",
string.Format("{0}%",
getPercentageSize((int)max, (int)min, tag.NumTags)));
// Add the HyperLink to the Panel.
TagCloud.Controls.Add(tagLink);
// Add a LiteralControl with a comma and a space.
TagCloud.Controls.Add(new LiteralControl(", "));
}
// Remove the last separator control from the Panel.
TagCloud.Controls.RemoveAt(TagCloud.Controls.Count - 1);
} else {
// Hide the tag cloud panel
TagCloud.Visible = false;
}
}
private int getPercentageSize(int max, int min, int score) {
// Ensure we've got a sensible number
if (min < 1) {
min = 1;
}
double spread = max - min;
if (spread == 0) {
spread = 1;
}
// Setup sensible bounds for the font sizes
int minSize = 80;
int maxSize = 200;
// Step ensures that our least used keyword is 80% and our
// most used is 200%
double step = (maxSize - minSize) / spread;
return (int)(minSize + ((score - min) * step));
}

Categories