I have not been able to find a solution regarding removing polylines from xamarin.forms.maps, there are plenty instances for googlemaps however.
Is it at all possible? Im not seeing anything obvious in the docs. I suppose that Im early enough into this project that I could probably switch over to googlemaps if need be.
int PointsCount = PointsInfoObj.Count;
for (int i = 0; i < PointsCount; i++)
{
//
// we want to ensure that the count is less than the final item, since the second point in a poly lands on the final
if (i < (PointsCount - 1))
{
Polyline polyLine = new Polyline
{
StrokeColor = Color.Blue,
StrokeWidth = 12,
Geopath =
{
//
// retrieve the current item and the next item for poyline drawing
new Position((double)PointsInfoObj[i].gpxPoints_Lattitude, (double)PointsInfoObj[i].gpxPoints_Longitude),
new Position((double)PointsInfoObj[(i+1)].gpxPoints_Lattitude, (double)PointsInfoObj[(i+1)].gpxPoints_Longitude)
}
};
//
// populate the polyline method
GPSMap.MapElements.Add(polyLine);
}
else continue;
}
//
// gather the first lat and last lon to do a proper MapSpan
double FirstLat = (double)PointsInfoObj[0].gpxPoints_Lattitude;
double LastLon = (double)PointsInfoObj[(PointsCount - 1)].gpxPoints_Longitude;
Console.WriteLine("lat: " + FirstLat + "---------------------------------------------");
Console.WriteLine("lon: " + LastLon + "---------------------------------------------");
GPSMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(FirstLat, LastLon), Distance.FromMiles(2.5)));
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.
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;
}
Hello I'm having a little trouble on this one aspect in my code that I'm working on. It deals with points and returns true or not if it's diagonal to other points in my arrayList of Points. Here my code so far:
private List<Point> point;
public void check()
{
for (int i = 0; i < point.Count; i++)
{
validSpot(i);
}
}
One note, your graph has your y upside down from the way an array stores it.
You could treat your indexes as points on a graph. To find what falls on the diagonal use slope intercept form. y = m x + b. Since you only want diagonals, valid slopes are limited to 1 and -1. Then you just have to define the line that passes through the point of interest and test if the point in question satisfies one of the equations for m = -1 or m = 1. Since the slope is known you only need one point to define the line.
public bool func(int[] knownPt,int xTest, int yTest)
{
//knownPt is int[]{x,y}
// y = m*x + (yi - xi)
return yTest== xTest + knownPt[1] - KnownPt[0] || yTest == -xTest +knownPt[1] + KnownPt[0];
}
As a walk through here is m = -1
yi = -xi + b
yi + xi = b
since b = yi + xi
y = -x + (yi + xi)
I'm writing a small application in C# using MSChart control to do Scatter Plots of sets of X and Y data points. Some of these can be rather large (hundreds of data points).
Wanted to ask if there's a 'standard' algorith for plotting a best-fit line across the points. I'm thinking to divide the X data points to a predefined number of sets, say 10 or 20, and for each set take the average of the corresponding Y values and the middle X value, and so on to create the line. Is this a correct approach?
I've searched existing threads but they all seem to be about achieving the same using existing applications like Matlab.
Thanks,
using a Linear least squares algorithm
public class XYPoint
{
public int X;
public double Y;
}
class Program
{
public static List<XYPoint> GenerateLinearBestFit(List<XYPoint> points, out double a, out double b)
{
int numPoints = points.Count;
double meanX = points.Average(point => point.X);
double meanY = points.Average(point => point.Y);
double sumXSquared = points.Sum(point => point.X * point.X);
double sumXY = points.Sum(point => point.X * point.Y);
a = (sumXY / numPoints - meanX * meanY) / (sumXSquared / numPoints - meanX * meanX);
b = (a * meanX - meanY);
double a1 = a;
double b1 = b;
return points.Select(point => new XYPoint() { X = point.X, Y = a1 * point.X - b1 }).ToList();
}
static void Main(string[] args)
{
List<XYPoint> points = new List<XYPoint>()
{
new XYPoint() {X = 1, Y = 12},
new XYPoint() {X = 2, Y = 16},
new XYPoint() {X = 3, Y = 34},
new XYPoint() {X = 4, Y = 45},
new XYPoint() {X = 5, Y = 47}
};
double a, b;
List<XYPoint> bestFit = GenerateLinearBestFit(points, out a, out b);
Console.WriteLine("y = {0:#.####}x {1:+#.####;-#.####}", a, -b);
for(int index = 0; index < points.Count; index++)
{
Console.WriteLine("X = {0}, Y = {1}, Fit = {2:#.###}", points[index].X, points[index].Y, bestFit[index].Y);
}
}
}
Yes. You will want to use Linear Regression, specifically Simple Linear Regression.
The algorithm is essentially:
assume there exists a line of best fit, y = ax + b
for each of your points, you want to minimise their distance from this line
calculate the distance for each point from the line, and sum the distances (normally we use the square of the distance to more heavily penalise points further from the line)
find the values of a and b that minimise the resulting equation using basic calculus (there should be only one minimum)
The wikipedia page will give you everything you need.